C++ C++;将一组值映射到类型
我的最终目标是实现从一组两个字符串到相应数据类型的映射:C++ C++;将一组值映射到类型,c++,c++11,templates,C++,C++11,Templates,我的最终目标是实现从一组两个字符串到相应数据类型的映射: "AA" --> char "BB" --> int "CC" --> float "DD" --> std::complex<double> and so on ... “AA”-->char “BB”-->int “CC”-->float “DD”-->std::complex 等等 我能想出的最好的“不太有效”的解决方案是两部分。第一部分是使用std::map在字符串和相应的枚举值之间进行映射
"AA" --> char
"BB" --> int
"CC" --> float
"DD" --> std::complex<double>
and so on ...
“AA”-->char
“BB”-->int
“CC”-->float
“DD”-->std::complex
等等
我能想出的最好的“不太有效”的解决方案是两部分。第一部分是使用std::map在字符串和相应的枚举值之间进行映射。第二部分使用模板化的类型别名和std::conditional将枚举值映射到类型
enum class StrEnum { AA, BB, CC, DD };
// STEP 1: string --> enum
// !! std::map will not work here since a constexpr is required !!
std::map<std::string, StrEnum> str_map = {
{"AA", StrEnum::AA},
{"BB", StrEnum::BB},
{"CC", StrEnum::CC},
{"DD", StrEnum::DD}
};
// STEP 2: enum --> type
template<StrEnum val> using StrType = typename std::conditional<
val == StrEnum::AA,
char,
typename std::conditional<
val == StrEnum::BB,
int,
typename std::conditional<
val == StrEnum::CC,
float,
std::complex<double>
>::type
>::type
>::type;
enum类强度{AA,BB,CC,DD};
//步骤1:字符串-->枚举
// !! std::map在这里不起作用,因为需要constexpr!!
std::map str\U map={
{“AA”,强度::AA},
{“BB”,强度::BB},
{“CC”,strengum::CC},
{“DD”,强度::DD}
};
//步骤2:枚举-->类型
使用StrType=typename std::conditional的模板<
val==强度::AA,
烧焦
类型名称std::条件<
val==强度::BB,
int,
类型名称std::条件<
val==强度::CC,
浮动
复杂的
>::类型
>::类型
>::类型;
目标用法:
StrType myVal;// 我最近做过类似的事情。我提出的解决方案是这样的(包含更多内容,但这里是主要思想):
//定义ID的类型
使用TypeIdentifier=size\u t;
//定义一个ID生成器
结构id_生成器{
静态类型标识符创建_id(){
静态TypeIdentifier值=0;
返回值++;
}
};
//为place定义某种类型的处理程序
结构类型\u id\u处理程序{
静态std::向量类型_处理器;
};
std::vector type\u id\u handler::type\u handler;
//定义id并创建基本函数
模板
结构类型\u id\u定义{
静态类型标识符get_id(){
静态TypeIdentifier id=id_生成器::创建_id();
静态自动一次性东西=[]()->bool{
type\u id\u handler::type\u handler.resize(id+1);
type_id_handler::type_handler[id]=[](void*ptr){
自动*对象=静态_转换(ptr);
//做你喜欢的事
std::cout由于std::map
没有常量表达式,因此无法在编译时计算模板参数str_map[“BB”]
将整数映射到类型的一种简单且可维护的方法是使用std::tuple
和std::tuple_元素
,如下所示。
例如,StrType
是char
,StrType
是int
,等等:
using types = std::tuple<char, int, float, std::complex<double>>;
template<std::size_t N>
using StrType = typename std::tuple_element<N, types>::type;
您可以将这些功能用于当前用途,如下所示:
StrType x;//x是int。
constexpr const char*float_type=“CC”;
StrType y;//y是float。
静态断言(std::is_same::value,“oops.”);//确定。
静态断言(std::is_same::value,“oops.”);//确定。
静态断言(std::is_same::value,“oops.”);//确定。
静态断言(std::is_same::value,“oops.”);//确定。
需要明确的是:您希望此映射在编译时工作吗?此代码是否实际按原样工作?可能适合您,但将两个字符键转换为类型可能会有点尴尬。请注意,您的代码缺少几个类型名
(在每个std::conditional
之前)符合要求。我想你是在使用MSVC?我对缺少的类型名不满意。我编辑了这篇文章来添加它们。我实际上是在使用gcc作为编译器。@Max Langhof,这种映射在编译时应该可以理想地工作。我想这基本上解决了这个问题。constexpr字符串比较函数是我从未想到的真正缺少的链接.
int main() {
std::map<std::string, TypeIdentifier> typeMap {
{"AA", type_id_define<char>::get_id()},
{"BB", type_id_define<int>::get_id()},
};
int a;
char b;
type_id_handler::type_handler[typeMap["BB"]](&a);
type_id_handler::type_handler[typeMap["AA"]](&b);
return 0;
}
type_id_define<T>::get_id()::<lambda()>::<lambda(void*)> [with T = int]
type_id_define<T>::get_id()::<lambda()>::<lambda(void*)> [with T = char]
using types = std::tuple<char, int, float, std::complex<double>>;
template<std::size_t N>
using StrType = typename std::tuple_element<N, types>::type;
constexpr bool strings_equal(const char* a, const char* b) {
return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1));
}
constexpr std::size_t getIdx(const char* name)
{
return strings_equal(name, "AA") ? 0:
strings_equal(name, "BB") ? 1:
strings_equal(name, "CC") ? 2:
strings_equal(name, "DD") ? 3:
4; // compilation error
}
StrType<getIdx("BB")> x; // x is int.
constexpr const char* float_type = "CC";
StrType<getIdx(float_type)> y; // y is float.
static_assert(std::is_same<StrType<getIdx("AA")>, char> ::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("BB")>, int> ::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("CC")>, float>::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("DD")>, std::complex<double>>::value, "oops."); // OK.