背景
最近沉迷于语法糖,并且最近在做项目的时候,总想着要把代码做的更精致、更严谨一些,就想到了用语法糖来检查类型是否存在,当然了实际开发中应该并不会使用这些。
所以…仅供参考!
方法
样例1
直接检查类的大小是否大于0,因为大家都知道即使是一个空类,它的大小也为1。
class bbb {};
#define TYPE_EXISTS0(T) \
(sizeof(char(*)[sizeof(T)]) > 0)
#define CHECK_TYPE0(ClassName) \
namespace { \
auto func0 = []() { \
static_assert(TYPE_EXISTS0(ClassName), #ClassName "Class does not define!"); \
return true; \
}(); \
}
CHECK_TYPE0(bbb);
样例2
使用 SFINAE(Substitution Failure Is Not An Error) 技术的编译期类型存在性检查工具。(C++11标准)
#include <type_traits>
class bbb {};
template<typename T, typename = void>
struct TYPE_EXISTS1 : std::false_type {};
template<typename T>
struct TYPE_EXISTS1<T, std::void_t<decltype(std::declval<T>())>> : std::true_type {};
#define CHECK_TYPE1(ClassName) \
namespace { \
auto func1 = []() { \
static_assert(TYPE_EXISTS1<ClassName>::value, #ClassName "Class does not define!"); \
return true; \
}(); \
}
CHECK_TYPE1(bbb);
详解:
- std::declval() 的作用
在编译期虚构一个 T 类型的右值引用(无需构造函数),等效于 T&&,但可以在不构造对象的情况下使用成员函数/运算符,如果 T 是无效类型(未定义或不完整),此处会触发替换失败。 - decltype 的编译时求值
decltype(std::declval()) 尝试获取虚构表达式的类型,若 T 是完整类型,返回 T&&;若 T 无效,SFINAE 会跳过该特化 - std::void_t 的魔法
std::void_t<…> 是一个模板元工具,当内部所有类型有效时生成 void;若 decltype(std::declval()) 有效,则特化版本匹配,继承 std::true_type;否则回退到基础模板的 std::false_type
样例3
同上,也是使用SFINAE(C++98标准)
class bbb {};
template<typename T>
struct TYPE_EXISTS2 {
private:
template<typename U>
static char test(typename U*);
template<typename>
static long test(...);
public:
static constexpr bool value = sizeof(test<T>(nullptr)) == sizeof(char);
};
#define CHECK_TYPE2(ClassName) \
namespace { \
auto func2 = []() { \
static_assert(TYPE_EXISTS2<ClassName>::value, #ClassName "Class does not define!"); \
return true; \
}(); \
}
CHECK_TYPE2(bbb);
2744

被折叠的 条评论
为什么被折叠?



