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.