8

渡された可変個引数型リストに重複する型がないかどうかhas_no_duplicates<...>を評価する型特性を実装したいと考えています。std::true_type

static_assert(has_no_duplicates<int, float>{}, "");
static_assert(!has_no_duplicates<float, float>{}, "");

この質問の範囲では、多重継承を使用してそれを行いたいと仮定しましょう。

クラスが同じ型を複数回継承すると、エラーが発生します。

template<class T> 
struct type { };

template<class... Ts>
struct dup_helper : type<Ts>... { };

// No errors, compiles properly.
dup_helper<int, float> ok{};

// Compile-time error: 
// base class 'type<float>' specified more than once as a direct base class
dup_helper<float, float> error{};

void_tこのエラーを「検出」するために使用できたと思いましたが、 cppreference のコード サンプルに従って実際の解決策を実装できませんでした。

これは私が試したものです:

template<class, class = void>
struct is_valid 
    : std::false_type { };

// First try:
template<class T>
struct is_valid<T, std::void_t<decltype(T{})>> 
    : std::true_type { };

// Second try:
template<class T>
struct is_valid<T, std::void_t<T>> 
    : std::true_type { };

3 回目の試行では、 のようにテンプレート テンプレート パラメータとして取り、内部で展開dup_helper<...>するラッパー クラスを使用して展開を遅らせてみました。dup_helperwrapper<dup_helper, ...>void_t

残念ながら、すべての試行で前述のエラーが発生し、常にコンパイルが妨げられました。

この種のエラーは「置換失敗」として検出できないと思いますが、確認をお願いします。


この種のエラーは実際に使用して検出することは不可能void_tですか? (常にコンパイルに失敗しますか?)

コンパイルを失敗させずにそれを検出する方法はありますか? (または、void_t「多重継承のトリック」を引き続き利用する非回避策)?

4

2 に答える 2

7

@Canoninosが指摘したように、問題は次のとおりです。

dup_helper<T, T>エラーを引き起こすのは宣言ではなく、その定義[...]です。

または、標準語では、置換の「即時コンテキスト」( [temp.deduct] ) の外側でエラーが発生します。

8 - [...]関数型とそのテンプレート パラメーター型の直接のコンテキストにある無効な型と式のみが、推論の失敗につながる可能性があります。[注:置換された型と式の評価は、クラス テンプレートの特殊化および/または関数テンプレートの特殊化のインスタンス化、暗黙的に定義された関数の生成などの副作用をもたらす可能性があります。 context」であり、プログラムの形式が正しくない可能性があります。—エンドノート]

ここでは、インスタンス化中 にエラーが発生するdup_helper<float, float>ため、「即時コンテキスト」にはありません。

あなたのものに非常に近い多重継承のトリックの 1 つは、複数のベースにインデックスを付けることによって、継承のレイヤーを追加することです。

helper<<0, 1>, <float, float>>        
             +            
        +----+----+       
        v         v       
 ix<0, float>  ix<1, float>
        +         +       
        v         v       
     t<float>  t<float>   

これにより、有効な定義を持つヘルパー クラスが得られます。これはインスタンス化できますが、あいまいさのために最終的な基本クラスにキャストできません。

static_cast<t<float>>(helper<...>{});  // Error, SFINAE-usable

于 2015-08-14T19:43:23.143 に答える