std:: void_t
| Type traits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time rational arithmetic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time integer sequences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(C++14)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ヘッダーで定義
<type_traits>
|
||
|
template
<
class
...
>
using void_t = void ; |
(C++17以降) | |
任意の型シーケンスを型 void にマッピングするユーティリティメタ関数。このメタ関数は、C++20の SFINAE 以前に concepts を活用する便利な方法であり、特に式が 未評価コンテキスト ( decltype 式のオペランドなど)で有効かどうかに基づいて、関数のオーバーロードや特殊化を条件付きで 候補セット から削除するために使用され、サポートされる操作に基づいて個別の関数オーバーロードや特殊化を存在させることを可能にします。
注記
このメタ関数は、SFINAEコンテキストにおいて不正な形式の型を検出するために、テンプレートメタプログラミングで使用されます:
// プライマリテンプレートはネストされた ::type メンバーを持たない型を処理する: template<class, class = void> struct has_type_member : std::false_type {}; // 特殊化はネストされた ::type メンバーを持つ型を認識する: template<class T> struct has_type_member<T, std::void_t<typename T::type>> : std::true_type {};
式の有効性を検出するためにも使用できます:
// 基本テンプレートは前置インクリメントをサポートしない型を扱う: template<class, class = void> struct has_pre_increment_member : std::false_type {}; // 特殊化は前置インクリメントをサポートする型を認識する: template<class T> struct has_pre_increment_member<T, std::void_t<decltype(++std::declval<T&>())> > : std::true_type {};
CWG issue 1558
(C++11の欠陥)が解決されるまで、
エイリアステンプレート
内の未使用パラメータはSFINAEを保証せず、無視される可能性があったため、以前のコンパイラでは
void_t
のより複雑な定義が必要でした。例えば:
template<typename... Ts> struct make_void { typedef void type; }; template<typename... Ts> using void_t = typename make_void<Ts...>::type;
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_void_t
|
201411L
|
(C++17) |
std::void_t
|
例
#include <iomanip> #include <iostream> #include <map> #include <type_traits> #include <vector> // 型がbegin()とend()メンバ関数を持つかチェックする変数テンプレート template<typename, typename = void> constexpr bool is_range = false; template<typename T> constexpr bool is_range<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> = true; // 反復対象コンテナのvalue_typeをvalue_typeとするイテレータ特性 // back_insert_iterator(value_typeがvoidの場合)もサポート template<typename T, typename = void> struct iterator_trait : std::iterator_traits<T> {}; template<typename T> struct iterator_trait<T, std::void_t<typename T::container_type>> : std::iterator_traits<typename T::container_type::iterator> {}; class A {}; #define SHOW(...) std::cout << std::setw(34) << #__VA_ARGS__ \ << " == " << __VA_ARGS__ << '\n' int main() { std::cout << std::boolalpha << std::left; SHOW(is_range<std::vector<double>>); SHOW(is_range<std::map<int, double>>); SHOW(is_range<double>); SHOW(is_range<A>); using container_t = std::vector<int>; container_t v; static_assert(std::is_same_v< container_t::value_type, iterator_trait<decltype(std::begin(v))>::value_type>); static_assert(std::is_same_v< container_t::value_type, iterator_trait<decltype(std::back_inserter(v))>::value_type>); }
出力:
is_range<std::vector<double>> == true is_range<std::map<int, double>> == true is_range<double> == false is_range<A> == false
関連項目
|
(C++11)
|
オーバーロード解決から関数オーバーロードまたはテンプレート特殊化を条件付きで
除去する
(クラステンプレート) |