namespace std {
template<class T, class U, template<class> class TQual, template<class> class UQual>
struct basic_common_reference {};
}
概要
任意の2つのプログラム定義型について、common_reference
で共通の参照型を取得できるようにアダプトする。
特殊化
basic_common_reference
は以下の条件を満たす場合に、型T, U
を対象に取るものに限ってユーザー定義の特殊化が許可されている(TQual, UQual
に対しては特殊化してはならない)。
T, U
の少なくとも片方はプログラム定義型に依存しているT, U
に対するdecay
の適用はともに恒等写像となるT, U
はともに配列型ではなくT, U
はともに関数型でもなくT, U
はともに参照型でもなくT, U
はともにCV修飾もされていない
そして、そのような特殊化は必ずしもメンバ型type
を持たなくても構わない。もしtype
を定義する場合はpublic
にただ一つだけ定義し、その型はTQual<T>, UQual<U>
から明示的に変換可能な型である必要がある。
なお、TQual<T>, UQual<U>
はそれぞれ、使用時にcommon_reference
に渡された実引数型の参照・CV修飾を対応するT, U
にそのままコピーしたような型を示すエイリアステンプレートである。
そして、その特殊化はT, U
の引数順を入れ替えても同じ結果を返す(対称性を持つ)必要がある。
上記のいずれかの規則に違反した特殊化を定義したとしてもコンパイルエラーにはならず、未定義動作を引き起こす。
なお、common_type, basic_common_reference
以外の<type_traits>
内テンプレートに対するユーザー定義の特殊化は許可されていない。
例
#include <iostream>
#include <type_traits>
#include <concepts>
//共通の参照型を作るための基底型
struct B {};
//std::common_referenceにアダプトしたい2つの型
struct T : B {};
struct U : B {};
//std::common_referenceおよびstd::common_reference_withにアダプトする
namespace std {
template<template<class> class TQual, template<class> class UQual>
struct basic_common_reference<T, U, TQual, UQual> {
using type = B&;
};
//対称性のために引数順を逆にしたものも定義する
template<template<class> class TQual, template<class> class UQual>
struct basic_common_reference<U, T, TQual, UQual> {
using type = B&;
};
}
int main()
{
static_assert(std::same_as<std::common_reference_t<T, U>, B&>);
static_assert(std::same_as<std::common_reference_t<U, T>, B&>);
}
出力
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 3 ✅
関連項目
参照
- P0898R3 Standard Library Concepts
- P2655R0
common_reference_t
ofreference_wrapper
Should Be a Reference TypeT&
とreference_wrapper<T>
のcommon_reference
をT&
にするためのbasic_common_reference
特殊化の例