namespace std {
template<class T, class U>
concept common_with =
same_as<common_type_t<T, U>, common_type_t<U, T>> &&
requires {
static_cast<common_type_t<T, U>>(declval<T>());
static_cast<common_type_t<T, U>>(declval<U>());
} &&
common_reference_with<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>> &&
common_reference_with<
add_lvalue_reference_t<common_type_t<T, U>>,
common_reference_t<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>>>;
}
概要
common_with
は、T, U
の間で、どちらの型からも変換可能な共通の型が存在することを表すコンセプトである。
2つの型T, U
はある型C
へ両方の型から明示的に変換可能な場合にのみ、共通型を持つ。このような型C
は、必ずしもT
やU
と同じ型である必要はなく、C
は一意で無くても良い。
モデル
C = common_type_t<T, U>
、等しさを保持しdecltype((t1))
とdecltype((t2))
が共にT
となるような式t1, t2
及び、等しさを保持しdecltype((u1))
とdecltype((u2))
が共にU
となるような式u1, u2
について以下の条件を満たす場合に限って、型T, U
はcommon_with
のモデルである。
t1
とt2
が等値である場合にのみ、C(t1)
とC(t2)
も等値となるu1
とu2
が等値である場合にのみ、C(u1)
とC(u2)
も等値となる
備考
このコンセプトをカスタマイズするには、common_type
を利用する。
例
#include <iostream>
#include <concepts>
#include <vector>
#include <string>
template<typename T, typename U>
requires std::common_with<T, U>
void f() {
std::cout << "T, U share a common type" << std::endl;
}
template<typename T, typename U>
void f() {
std::cout << "T, U not share a common type" << std::endl;
}
int main()
{
f<std::size_t&, int&>();
f<std::string&, std::string_view&>();
f<std::vector<int>, std::vector<int>&>();
f<std::vector<int>, std::vector<double>>();
f<std::pair<int&, double&>, std::pair<int, double>>();
}
25
#include <iostream>
#include <concepts>
#include <vector>
#include <string>
template<typename T, typename U>
requires std::common_with<T, U>
void f() {
std::cout << "T, U share a common type" << std::endl;
}
template<typename T, typename U>
void f() {
std::cout << "T, U not share a common type" << std::endl;
}
int main()
{
出力
T, U share a common type
T, U share a common type
T, U share a common type
T, U not share a common type
T, U share a common type
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 3 ✅