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
預設模闆,總是最後才會執行比對。