パラメータの順序に依存しない一般化された形式のstd :: same_as(つまり、3つ以上の型パラメータ)を実装するにはどうすればよいですか?

ケンビョウ凛

バックグラウンド

私たちは、概念があることを知っている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]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ