私たちは、概念があることを知っているstd::same_as
(対称言い換えれば、)順序にとらわれない:std::same_as<T, U>
と等価であるstd::same_as<U, T>
(関連質問)。この質問では、より一般的なものを実装したいと思います。それはtemplate <typename ... Types> concept same_are = ...
、パック内のタイプTypes
が互いに等しいかどうかをチェックします。
#include <type_traits>
#include <iostream>
#include <concepts>
template <typename T, typename... Others>
concept same_with_others = (... && std::same_as<T, Others>);
template <typename... Types>
concept are_same = (... && same_with_others<Types, Types...>);
template< class T, class U> requires are_same<T, U>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
// Note the order <U, T> is intentional
template< class T, class U> requires (are_same<U, T> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
(ここでの私の意図は、パック内のすべての可能な順序対のタイプを列挙することです)
残念ながら、このコードはコンパイルされず、コンパイラfoo(int, int)
はへの呼び出しがあいまいであると文句を言います。私はそれが同等are_same<U, T>
でare_same<T, U>
はないと考えていると信じています。コードが失敗する理由を知りたいのですが、どうすれば修正できますか(コンパイラがそれらを同等として扱うように)?
問題は、この概念では、次のとおりです。
template <typename T, typename... Others>
concept are_same = (... && std::same_as<T, Others>);
この概念の正規化された形式は...まさにそれです。これを「展開」することはできず(何もすることはありません)、現在のルールは概念の「部分」を通じて正規化されません。
言い換えれば、これが機能するために必要なのは、概念を次のように正規化することです。
... && (same-as-impl<T, U> && same-as-impl<U, T>)
に:
... && (is_same_v<T, U> && is_same_v<U, T>)
また、あるフォールド式&&
制約が他のフォールド式制約を包含している&&
場合、その基礎となる制約が他のフォールド式制約を包含していると考えてください。そのルールがあれば、それはあなたの例を機能させるでしょう。
将来的にこれを追加することは可能かもしれませんが、包含ルールに関する懸念は、コンパイラーが制約の包含をチェックするために完全なSATソルバーを実装することを要求したくないということです。これはそれほど複雑にはならないようですが(実際には、fold-expressionsを介してルール&&
と||
ルールを追加するだけです)、私にはまったくわかりません。
ただし、このようなフォールド式の包含are_same<T, U>
があったとしても、それでも包含しないことに注意してくださいstd::same_as<T, U>
。包み込むだけare_same<U, T>
です。これが可能かどうかはわかりません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加