c++ - 如何构建可以附加类型的类型的 constexpr 向量?
问题描述
我的同事挑战我构建一个TypeVector
,它是编译时类似向量的容器,它可以在编译时 push_back 类型和删除类型。给定一个 constexpr TypeVector
,您应该能够从TypeVector
.
TypeVector 的伪代码示例用法:
consteval auto build_vector() {
TypeVector<2> x; //TypeVector of size 2
x.push_back(int);
x.push_back(float);
return x;
}
static constexpr auto my_vector = build_vector();
// Get type from first element of my_vector
typename retrieve_type<my_vector.get<0>()>::type some_variable = 0; // equivalent to int some_variable = 0;
// Get type from second element of my_vector
typename retrieve_type<my_vector.get<1>()>::type some_variable2 = 0.0f; // equivalent to float some_variable2 = 0.0f;
我认为最好的方法是使用std::array
问题是std::array
不能存储类型但需要存储相同类型的值,所以我将类型转换为如下值:
template <typename T>
struct TypeHash{
static constexpr char obj; // Create one obj per type
static constexpr char* value = &obj; // This will be different for each type
};
template <typename T>
static constexpr char* to_value = TypeHash<T>::value;
// Now I can do to_value<int> and to_value<float> to "store" the float and int as values of type const char*
// Example usage:
template <int N>
using TypeVector<N> = std::array<const char*, N>;
consteval auto some_func() {
TypeVector<2> x;
x[0] = to_value<int>;
x[1] = to_value<float>;
return x;
}
static constexpr auto first_type = some_func()[0];
问题是反转这个操作:retrieve_type
从伪代码创建。
我想通过模板专业化创建retrieve_type
一个const char*
类型映射,如下所示:
static constexpr auto first_type = some_func()[0]; // From above
template < const char* value> struct retrieve_type {};
template <> struct retrieve_type<to_value<int>> { using type = int; };
template <> struct retrieve_type<to_value<float>> { using type = float; };
// Now I can get the actual type from first type:
typename retrieve_type<first_type>::type y = 0; // int x = 0;
这种方法存在一些问题:
我必须
retrieve_type
为每个现有类型创建一个专业化(不是一个大问题,我可以处理这个,但这并不理想)(更大的问题)如何
retrieve_type
为模板创建专业化?
template <typename T>
struct SomeTemplateClass {};
// How to create a specialisation of retrieve_type for all instantiations of SomeTemplateClass?
我怎样才能使这个工作适用于从模板实例化的类型?我可以避免retrieve_type
为每种类型手动创建专业化吗?
我愿意使用任何第三方库/任何编译器特定选项。
解决方案
模板可以双射映射到类型。
template<class T>
strict tag_t{using type=T;};
template<class T>
constexpr tag_t<T> tag={};
template<template<class...>class Z>
struct ztemplate{
template<class...Ys>
constexpr auto operator()(tag_t<Ys>...)const{
return tag<Z<Ys...>>;
}
};
这处理一类模板。
如果你解决了值到类型映射问题,你可以解决值到模板问题。上面的模板只是类型标签上的无状态 constexpr 函数对象。
对于非类型模板参数,您需要不同的标记类型和不同的无状态 function.objects。例如,采用 std 整数常量类型的模板可以包装采用整数值的模板,使其表现更好。
至于要输入的值,那只是一个冗长的冗长冗长的口号。
您可以在整数的平面列表中构建解析树。
每个节点都有一个值和一个子节点计数,都是 constexpr。您通过标签调度获取第一个值并映射到标签类型。如果元素的数量大于 1,则使用从整数列表生成的递归评估类型标签调用标签调度结果。
template<std::size_t I>
using index_t=std::integral_constant<std::size_t,I>;
template<std::size_t I>
constexpr index_t<I> index{};
constexpr tag_t<int> map_to_type(index_t<0>){return {};}
constexpr ztemplate<std::vector> map_to_type(index_t<1>){return {};}
constexpr auto make_type(){
constexpr int arr[]={1,0};
return map_to_type(index<arr[0]>)(map_to_type(index<arr[1]>));
}
constexpr auto tag=make_type();
decltype(tag)::type vec={1,2,3};
推荐阅读
- javascript - 赛普拉斯的 before 和 beforeEach 究竟是如何工作的?
- javascript - 如何获得奖励视频以在 cordova-plugin-admob-free 上工作?
- angular - Angular Fire Store - 错误“没有与类型 'GetOptions' 相同的属性。”
- bash - Bash:如何使用正则表达式搜索文件中的字符串并获取相关值
- asp.net-core - .NET Core 2.2 - “HTTP 错误 500.30 - ANCM 进程内启动失败”
- python - Scikit-learn LabelEncoder:IndexError:用作索引的数组必须是整数(或布尔)类型
- curl - 如何将多行字符串发送到 curl 字段?
- java - 基于模板 - 代码生成器框架或工具
- android - 将 Android 源代码打包到手机应用程序中的步骤?
- spring - 将 SpringMVC 与 JSP 页面一起使用时出现错误 500