std::common_reference
| ヘッダ <type_traits> で定義 |
||
| template< class... T > struct common_reference; |
(C++20以降) | |
型 T... の共通参照型を決定します。これは、T... 内のすべての型が変換またはバインドできる型です。そのような型が存在する場合(以下のルールに従って決定されます)、メンバー type がその型を指します。そうでない場合、メンバー type は存在しません。T... 内のいずれかの型が、(おそらくcv修飾された)void 以外の不完全型である場合、動作は未定義です。
参照型が与えられた場合、common_reference は提供された参照型すべてがバインドできる参照型を見つけようとしますが、そのような参照型が見つからない場合は非参照型を返すことがあります。
- sizeof...(T) がゼロの場合、メンバー
typeは存在しません。 - sizeof...(T) が1の場合(つまり、
T...が1つの型T0のみを含む場合)、メンバーtypeは T0 と同じ型を指します。 - sizeof...(T) が2の場合(つまり、
T...が2つの型T1とT2を含む場合)- 型
SをT1とT2の単純共通参照型とします(以下で定義)。以下の条件がすべて満たされる場合、メンバー型typeはSを指します。-
T1とT2の両方が参照型である -
Sが整形式である
-
- 型
|
(C++23から) |
- そうでない場合、std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type が存在する場合、ここで
TiQは単項エイリアステンプレートであり、TiQ<U> はTiの cv修飾子と参照修飾子を追加したUである場合、メンバー型typeはその型を指します。
- そうでない場合、std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type が存在する場合、ここで
- そうでない場合、decltype(false? val<T1>() : val<T2>()) が有効な型である場合、ここで
valは関数テンプレート template<class T> T val(); である場合、メンバー型typeはその型を指します。 - そうでない場合、std::common_type_t<T1, T2> が有効な型である場合、メンバー型
typeはその型を指します。 - そうでない場合、メンバー
typeは存在しません。
- そうでない場合、decltype(false? val<T1>() : val<T2>()) が有効な型である場合、ここで
- sizeof...(T) が2より大きい場合(つまり、
T...が型T1, T2, R...で構成される場合)、std::common_reference_t<T1, T2> が存在する場合、メンバーtypeは、そのような型が存在すれば std::common_reference_t<std::common_reference_t<T1, T2>, R...> を表します。その他すべての場合、メンバーtypeは存在しません。
2つの参照型 T1 と T2 の単純共通参照型は次のように定義されます。
T1がcv1 X&で、T2がcv2 Y&である場合(つまり、両方が左辺値参照型である場合):それらの単純共通参照型は decltype(false? std::declval<cv12 X&>() : std::declval<cv12 Y&>()) です。ここで cv12 は cv1 と cv2 の結合であり、その型が存在し、かつ参照型である場合。T1とT2の両方が右辺値参照型である場合:T1&とT2&の単純共通参照型(前述の箇条書きに従って決定される)が存在する場合、その型の対応する右辺値参照型をCとします。std::is_convertible_v<T1, C> および std::is_convertible_v<T2, C> の両方が true である場合、T1とT2の単純共通参照型はCです。- そうでない場合、2つの型のうち1つが左辺値参照型
A&で、もう1つが右辺値参照型B&&でなければなりません(AとBは cv修飾されている可能性があります)。存在する場合、A& と B const& の単純共通参照型をDとします。D が存在し、std::is_convertible_v<B&&, D> が true である場合、単純共通参照型はDです。 - そうでない場合、単純共通参照型は存在しません。
上記で使用されているような式 false ? X : Y の型の定義については、条件演算子を参照してください。
目次 |
[編集] メンバー型
| 名前 | 定義 |
type
|
すべての T... の共通参照型 |
[編集] ヘルパー型
| template< class... T > using common_reference_t = std::common_reference<T...>::type; |
||
| template< class T, class U, template<class> class TQual, template<class> class UQual > struct basic_common_reference {}; |
||
クラステンプレート basic_common_reference は、ユーザー定義型(通常はプロキシ参照)の common_reference の結果にユーザーが影響を与えることを可能にするカスタマイゼーションポイントです。プライマリテンプレートは空です。
[編集] 特殊化
プログラムは、std::is_same_v<T, std::decay_t<T>> および std::is_same_v<U, std::decay_t<U>> の両方が true であり、かつそれらの少なくとも1つがプログラム定義型に依存する場合、最初の2つのパラメータ T と U に対して std::basic_common_reference<T, U, TQual, UQual> を特殊化できます。
このような特殊化が type という名前のメンバーを持つ場合、それは TQual<T> と UQual<U> の両方が変換可能な型を指す、publicかつ曖昧さのないメンバーでなければなりません。さらに、std::basic_common_reference<T, U, TQual, UQual>::type と std::basic_common_reference<U, T, UQual, TQual>::type は同じ型を指す必要があります。
プログラムは、3番目または4番目のパラメーターに対して basic_common_reference を特殊化することはできませんし、common_reference 自体を特殊化することもできません。これらのルールに違反して特殊化を追加するプログラムの動作は未定義です。
標準ライブラリは、basic_common_reference の以下の特殊化を提供します。
2つのpairの共通参照型を決定する(クラステンプレート特殊化) | |
tuple と tuple-like 型の共通参照型を決定する(クラステンプレート特殊化) | |
reference_wrapper と非 reference_wrapper の共通参照型を決定します。(クラステンプレート特殊化) |
[編集] 注釈
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_common_reference |
202302L |
(C++23) | std::reference_wrapper の std::common_reference_t を参照型にする |
[編集] 例
#include <concepts> #include <type_traits> static_assert( std::same_as< int&, std::common_reference_t< std::add_lvalue_reference_t<int>, std::add_lvalue_reference_t<int>&, std::add_lvalue_reference_t<int>&&, std::add_lvalue_reference_t<int>const, std::add_lvalue_reference_t<int>const& > > ); int main() {}
[編集] 関連項目
| (C++11) |
型のグループの共通の型を決定する (クラステンプレート) |
| (C++20) |
2つの型が共通の参照型を共有することを規定する (コンセプト) |