興味深い質問です。私は最近、コンセプトに関するAndrew Suttonの講演を見て、Q&Aセッションで誰かが次の質問をしました(次のリンクのタイムスタンプ):
CppCon 2018:Andrew Sutton「60のコンセプト:知っておくべきことすべて、あなたが知らないこと」
したがって、質問は次のように要約されますIf I have a concept that says A && B && C, another says C && B && A, would those be equivalent?
。Andrewは「はい」と回答しましたが、コンパイラにはいくつかの内部メソッド(ユーザーには透過的)があり、概念をアトミックな論理命題に分解して(atomic constraints
Andrewが用語を述べたように)、それらがそうであるかどうかを確認します同等。
次に、cppreferenceが何について述べているかを見てくださいstd::same_as
。
std::same_as<T, U>
包含std::same_as<U, T>
およびその逆。
それは基本的に「if-and-only-if」関係であり、それらは互いに意味します。(論理的同等性)
私の推測では、ここに原子制約がありstd::is_same_v<T, U>
ます。コンパイラは、治療方法は、std::is_same_v
それらを考えさせるかもしれないstd::is_same_v<T, U>
し、std::is_same_v<U, T>
二つの異なる制約(それらが異なる実体である!)など。したがってstd::same_as
、そのうちの1つだけを使用して実装する場合:
template< class T, class U >
concept same_as = detail::SameHelper<T, U>;
その後std::same_as<T, U>
、std::same_as<U, T>
異なる原子制約に「爆発」し、同等ではなくなります。
さて、コンパイラはなぜ気にするのですか?
この例を考えてみましょう:
#include <type_traits>
#include <iostream>
#include <concepts>
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
// template< class T, class U >
// concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
template< class T, class U> requires my_same_as<U, T>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
template< class T, class U> requires (my_same_as<T, U> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
理想的には、my_same_as<T, U> && std::integral<T>
包含しmy_same_as<U, T>
ます。したがって、コンパイラーは2番目のテンプレート特殊化を選択する必要がありますが、それ以外は選択しません。コンパイラーはエラーを発行しますerror: call of overloaded 'foo(int, int)' is ambiguous
。
この背後にある理由は、以来ということですmy_same_as<U, T>
し、my_same_as<T, U>
お互いを包摂しない、my_same_as<T, U> && std::integral<T>
とmy_same_as<U, T>
(包摂の関係の下で制約の半順序集合上)無類なります。
ただし、交換した場合
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
と
template< class T, class U >
concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
コードがコンパイルされます。
SameHelper<T, U>
本当かもしれないからといって、そうであるとは限らないSameHelper<U, T>
。