std::nullptr_t
std::nullptr_t
是nullptr
的模板类型,用法如下:
#include <iostream>
#include <type_traits>
void foo(int *) {
std::cout << "int*\n";
}
void foo(double *) {
std::cout << "double*\n";
}
void foo(std::nullptr_t) {
std::cout << "nullptr\n";
}
int main() {
int *a = nullptr;
double *b = nullptr;
foo(a);
foo(b);
foo(nullptr); // (1)
return 0;
}
/*
int*
double*
nullptr
*/
(1)中,如果没有 std::nullptr_t
,nullptr
不知道应该匹配int*
还是double*
std::void_t
该模板的定义如下:
template< class... >
using void_t = void;
看起来没啥卵用,这个需要和SFINAE结合使用。举个例子,判定传入的结构是否包含tp
类型:
#include <iostream>
#include <utility>
// 泛型模板
template<typename T, typename = void>
struct HasTypeFoo : std::false_type {
};
// 模板特化,T::tp 特化的模板
template<typename T>
struct HasTypeFoo<T, std::void_t<typename T::tp>> : std::true_type {
};
struct Foo {
using tp = int;
};
struct FooFake {
using tp1 = double;
};
struct SubFoo : Foo {
using tp2 = float;
};
int main() {
std::cout << HasTypeFoo<Foo>::value << std::endl;
std::cout << HasTypeFoo<FooFake>::value << std::endl;
std::cout << HasTypeFoo<SubFoo>::value << std::endl;
return 0;
}
上面的代码中,HasTypeFoo
是泛型模板。如果泛型T
有tp
类型成员,那么会特化成std::void_t
类型;否则匹配失败,SFINAE 规则会自动匹配typename = void
的候选类型。
这里的代码中,std::void_t
的左右就是为了模板特化。因为typename = void
默认模板,总是最后才会执行匹配。