2017-09-19 9 views
18

の場合、互換非型テンプレートパラメータのプレースホルダ型である単純な例を考えてみましょう:は、テンプレートテンプレートパラメータ

int x; 

template <template <auto> class TT> 
struct Foo { 
    void foo() { 
     TT<(x)> tt; 
     static_cast<void>(tt); 
    } 
}; 

template <decltype(auto)> 
struct Bar { }; 


int main() { 
    Foo<Bar> foobar; 
    foobar.foo(); 
} 

[clang]は、テンプレートテンプレートパラメータでautoの使用にもかかわらずdecltype(auto)プレースホルダのアイデアを扱うように見えます宣言しても問題ありません。一方、

[gcc] - ない非常によくは:

として通常

prog.cc:6:13: error: the value of 'x' is not usable in a constant expression


- 標準に従った行動を期待されていますか?あるいは、すべてが可能であり、コードが不正です(今回は私が想定していませんが、決定的にそれを排除することはできません)。

PS。 )

+2

テンプレートパラメータに '(x)'を指定する方法はわかりません。ここで 'x'は変数ですが、どの種類のテンプレートでも有効です。私が最後にチェックしたのは、テンプレートパラメータは型または定数だけでした。 –

+5

@SamVarshavchik 'decltype(auto)'の場合、変数にはもちろんリンクがある限り(これが実際に有効であることを確認した最後の時間)変数を参照するように解決されます) –

+2

これは、 。 –

答えて

7

元の回答はFoo<Bar>でした。私は実際には今は整形式だと思っています。しかし、最終的に、clangバグに基づいています。


私は実際にもFoo<Bar>が悪い形成されていると思います。

A template-argument matches a template template-parameterP when P is at least as specialized as the template-argumentA

A template template-parameterP is at least as specialized as a template template-argumentA if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates ([temp.func.order]). Given an invented class template X with the template parameter list of A (including default arguments):

  • Each of the two function templates has the same template parameters, respectively, as P or A .
  • Each function template has a single function parameter whose type is a specialization of X with template arguments corresponding to the template parameters from the respective function template where, for each template parameter PP in the template parameter list of the function template, a corresponding template argument AA is formed. If PP declares a parameter pack, then AA is the pack expansion PP... ([temp.variadic]); otherwise, AA is the id-expressionPP .

If the rewrite produces an invalid type, then P is not at least as specialized as A .

Foo<Bar>自体は大丈夫であるかどうかを検証することを意味し、我々は合成:

template <decltype(auto) I> struct X; 

template <auto I>   void __f(X<I>); // P 
template <decltype(auto) I> void __f(X<I>); // A 

すべての種類P0522新ルールは、ということですここでは有効です(最後のステートメントは適用されません)。ここで、通常、部分的な順序付けを行うときは、オーバーロードの解決またはクラステンプレートの特殊化の選択のコンテキストになります。この場合、FFがの場合、Fmore specialized thanGの場合は、ファンクションテンプレート"more specialized"です。 GGは少なくともFと同じく特化していません。

しかし、この文脈では、私たちはどちらがより専門的であるか気にしません。我々はPが少なくともAと専門化されていればよい。つまり、控除額はAからPに引き上げられなければなりません。だから、もしある値Vを持つユニークなタイプUを合成すると、X<I>X<V>から推測できますか?はい。したがって、Pは少なくともAとして特化されているので、テンプレート引数BarはテンプレートパラメータTTと一致します。


ここで、この点を過ぎて、私はこれをクランバグといいます。テンプレートテンプレートパラメータtemplate <auto>です。これは、式の検証に使用するものです。非タイプのテンプレートパラメータautoを使用すると、xを値として使用しようとしますが、xは有効な定数式ではないため、これは失敗します。clangはtemplate <decltype(auto) >を直接使用しているようです - これはわかりませんが、有効です。

しかし、私はこの事件が考慮されているかどうかはわかりません - 私はどちらかの言い方を見ないし、問題を提起する価値があると言います。

関連する問題