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_tofreference_wrapperShould Be a Reference TypeT&とreference_wrapper<T>のcommon_referenceをT&にするためのbasic_common_reference特殊化の例