2017-04-07 6 views
1

私の質問は、次のコードが有効であるかどうか、次のとおりです。static_assertは

template<int i> class Class 
{ 
    static_assert(sizeof(i) == 0, "Class instantiated with i != 1"); 
}; 

template<> class Class<1> {}; 

このスニペットはg++でコンパイルされます。しかしclang++static_assertによってトラップされています

error: static_assert failed "Class instantiated with non-int type" 

代わりint

よう
template<typename T> class Class 
{ 
    static_assert(sizeof(T) == 0, "Class instantiated with non-int type"); 
}; 

template<> class Class<int> {}; 

の種類を使用するテンプレートは、両方のコンパイラで受け入れられています。関数テンプレートにはまったく同じパターンが適用されます。

open-std.org::Non-dependent static_assert-declarationsが見つかりましたが、私のstatic_assertはテンプレートパラメータに依存しているため適用されていません。

あなたはgodbolt.org

EDIT上で説明した動作を確認することがあります。ヨハン・ランドバーグはコメントで指摘するように、私の質問が間違っています。確かにsizeof(i)はテンプレートパラメータに依存しません。また、R.Sahuは完全に正しいです:それはi != 1を主張する方がはるかに意味があるでしょう。このために、両方のコンパイラがコードを受け入れます。

ただし、上の例はg++でコンパイルされます。 open-std.org::Non-dependent static_assert-declarationsがこのケースに当てはまるので(私はこの点について間違った質問をして再び謝罪します):g++はエラーなしでコードをコンパイルするのに実際に間違っていますか?テンプレートは、間違った型でインスタンス化されていることを主張したい場合

+5

私はあなたが正しいとは思わない「私のstatic_assertは、テンプレートパラメータに依存しているからです。」。 sizeof(i)はiの* value *に依存しません。 –

+0

最初の例でsizeofを使用する理由は何ですか? iはint型でsizeof(i)はsizeof(int)と同じです。おそらくアサーションで、私は直接私を使用したいと思う。 – Fabio

+2

'static_assert(i!= 1、" i!= 1 "でインスタンス化されたクラス);を使用することを意味しましたか? –

答えて

1

打ち鳴らす++は右であることが必要として

intのための専門を削除し、デフォルトの専門の非int型のクラスをinstanciatingは、両方のコンパイラでエラーが生成さあなたのコードを拒否することができますが、g ++はエラーを捕らえるのに間違っているわけではありません。これは「診断不要」の状況です。

標準では、テンプレート内の式を「型依存型」および/または「値依存型」として厳密に定義しています。 template<int i>を指定すると、iは値に依存しますが、タイプに依存しません。

[14.6.2.2/4]: Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):

  • ...
  • sizeofunary-expression
  • ...

[14.6.2.3/2]: Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:

  • sizeofunary-expression
  • ...

したがってsizeof(i)は依存しません。

最後に、14.6/8の言葉:

If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.

0

まず、あなたがstatic_assertで明示的に指定する必要があります。

第二
#include <type_traits> 

template<typename T> class Class 
{ 
    static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type"); 


}; 

、次の行は、あなたが何を考えてやってできないことがあります。あなたが実際にここで何をやっている

template<> class Class<int> {}; 

は、デフォルトのテンプレートの特殊Class<T>を行うには全く何もしています全く新しい専門分野を、作成しています。例えば、エラー

int main() 
{ 
    Class<int> ci; 
    Class<float> cf; 
} 

<source>: In instantiation of 'class Class<float>': 
<source>:14:18: required from here 
<source>:5:5: error: static assertion failed: Class instantiated with non-int type 
    static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type"); 
    ^~~~~~~~~~~~~ 
+0

あなたの答えをありがとう。しかし私はあなたのアイデアが私のものとは多少異なると思います。私は、(有用な)デフォルト実装を持たないクラスを考えていますが、いくつかの(1つだけではない)スペシャライゼーションを提供しています。これにより、コンパイル時に適切な実装を選択できます。 'static_assert'は、読みやすいエラーメッセージだけを提供します。 – marlam

+0

@marlam right ...しかし、あなたが定義するそれぞれの特殊化は全く新しいクラスを表しており、そのクラスには 'static_assert'がありません。 'Class 'を定義していて、インスタンス化していません。 –

+0

正解、それは私が言ったことです。 'static_assert'がすべてのスペシャライゼーションに含まれていれば、このアイデアに反するでしょう。しかし、私たちはまだ 'g ++'がなぜ最初のスニペットを受け入れるのかという疑問を持っています(質問の編集を見てください)。 – marlam

関連する問題