std::void_t是C++17中引入的,它其实是一个别名模板,源码非常简单,大概如下:
templateusing void_t = void;
从源码来看,无论传入什么类型,也无论传入多少个类型,都会变成void类型。但是它有一个神奇的功能,它能够检测到应用SFINAE特性时非法的类型,也就是说,传入的类型必须是有效的类型,不能是非法的类型。
接下来看个例子:判断类中是否存在某个类型别名
struct hasType {
using intType = int;
void fun() {}
};
struct noType {
void fun() {}
};
template>
struct HasTypeMem :std::false_type
{
};
template
struct HasTypeMem > :std::true_type
{
};
int main()
{
cout << HasTypeMem::value << endl;
cout << HasTypeMem::value << endl;
system("pause");
return 0;
}
结果:
调用 HasTypeMem时, 首先选用特化模板, 发现noType::intType 不存在,根据 SFINAE 原则, 不会产生模板代码. 编译器会走泛化版本,而泛化版本继承自false_type,所以打印0.
调用 HasTypeMem时, 首先选用特化模板, 发现hasType::intType 存在,则被优先考虑使用。于是打印1.
但是这个范例有一定的局限性,就是HasTypeMem的特化版本中,::type这个别名是写死的,如果判断的别名不叫intType,而是叫做MyType呢?看如下改进。
struct hasType {
using intType = int;
void fun() {}
};
struct noType {
void fun() {}
};
struct YES_Type {
using MyType = int;
void fun() {}
};
struct NO_Type {
void fun() {}
};
template>
struct HasTypeMem :std::false_type
{
};
template
struct HasTypeMem > :std::true_type
{
};
#define _HASTYPEMEM_(parMTpNm)
template>
struct HTM_##parMTpNm :std::false_type{};
template
struct HTM_##parMTpNm > :std::true_type{};
_HASTYPEMEM_(intType);
_HASTYPEMEM_(MyType);
int main()
{
cout << HTM_intType::value << endl;
cout << HTM_intType::value << endl;
cout << HTM_MyType::value << endl;
cout << HTM_MyType::value << endl;
system("pause");
return 0;
}
结果:
通过宏定义,我们实现了想要的功能,提高了代码的利用率。



