typedef类型别名运行时识别问题:如何区分同基类型的别名?
问题:区分typedef定义的同基础类型别名
你的C++代码如下:
#include <iostream> #include <type_traits> typedef char stringType1; typedef char stringType2; typedef enum { myType_noType, // 0 myType_stringType1, // 1 myType_stringType2 // 2 } MyDataType_t; //TYPE CHECK template <typename T> constexpr MyDataType_t TYPE_NAME(T x) { if constexpr (std::is_same<decltype(x),stringType1>::value){return myType_stringType1;} if constexpr (std::is_same<decltype(x),stringType2>::value){return myType_stringType2;} return myType_noType; } template <typename T> MyDataType_t myFunction(T *value) { return TYPE_NAME(*value); } int main() { std::cout<<"Hello World"<< std::endl; stringType1 var1; stringType2 var2; MyDataType_t aTypeId = myFunction(&var1); std::cout << aTypeId << std::endl; aTypeId = myFunction(&var2); std::cout << aTypeId << std::endl; return 0; }
运行结果:
Hello World 1 1
问题原因
typedef只是给已有类型起别名,stringType1和stringType2本质上都是char类型,编译器不会把它们视为独立的类型。因此std::is_same会判定两者完全相同,导致TYPE_NAME函数无法区分,最终返回同一个枚举值。
解决方案
要区分这两种类型,必须创建真正独立的类型,以下是两种可行方案:
方案1:用结构体包装基础类型
通过结构体封装char,生成完全独立的新类型,编译期就能明确区分:
#include <iostream> #include <type_traits> // 用结构体包装char,生成不同的类型 struct stringType1 { char value; }; struct stringType2 { char value; }; enum class MyDataType_t { myType_noType, myType_stringType1, myType_stringType2 }; template <typename T> constexpr MyDataType_t TYPE_NAME(const T& x) { if constexpr (std::is_same_v<T, stringType1>) { return MyDataType_t::myType_stringType1; } else if constexpr (std::is_same_v<T, stringType2>) { return MyDataType_t::myType_stringType2; } else { return MyDataType_t::myType_noType; } } template <typename T> MyDataType_t myFunction(const T* value) { return TYPE_NAME(*value); } int main() { std::cout << "Hello World" << std::endl; stringType1 var1; stringType2 var2; auto aTypeId = myFunction(&var1); std::cout << static_cast<int>(aTypeId) << std::endl; // 输出1 aTypeId = myFunction(&var2); std::cout << static_cast<int>(aTypeId) << std::endl; // 输出2 return 0; }
方案2:利用模板别名+标签类型
如果需要保留类似typedef的语法,同时区分类型,可以结合模板别名和标签类型:
#include <iostream> #include <type_traits> // 定义标签类型,用于区分 struct Tag1 {}; struct Tag2 {}; // 模板别名,绑定标签和char类型 template <typename Tag> using TaggedChar = char; using stringType1 = TaggedChar<Tag1>; using stringType2 = TaggedChar<Tag2>; enum class MyDataType_t { myType_noType, myType_stringType1, myType_stringType2 }; // 通过函数重载区分不同标签的类型 constexpr MyDataType_t TYPE_NAME(TaggedChar<Tag1>) { return MyDataType_t::myType_stringType1; } constexpr MyDataType_t TYPE_NAME(TaggedChar<Tag2>) { return MyDataType_t::myType_stringType2; } template <typename T> constexpr MyDataType_t TYPE_NAME(T) { return MyDataType_t::myType_noType; } template <typename T> MyDataType_t myFunction(T* value) { return TYPE_NAME(*value); } int main() { std::cout << "Hello World" << std::endl; stringType1 var1; stringType2 var2; auto aTypeId = myFunction(&var1); std::cout << static_cast<int>(aTypeId) << std::endl; // 输出1 aTypeId = myFunction(&var2); std::cout << static_cast<int>(aTypeId) << std::endl; // 输出2 return 0; }
说明
- 方案1的结构体包装是最直观的方式,每个结构体都是独立类型,使用时需要通过
.value访问底层char。 - 方案2的模板别名+标签类型,既保留了char的所有特性(可以直接当作char使用),又能让编译器识别为不同类型,适合需要兼容原有char操作的场景。
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

