2013-12-09 28 views
25

このコードがエラーなしでコンパイルなぜ私は理解していない:無効になっていますか?

#include <iostream> 

template <class T> 
struct Test 
{ 
    static constexpr T f() {return T();} 
}; 

int main() 
{ 
    Test<void> test; 
    test.f(); // Why not an error? 
    return 0; 
} 

は、それが標準に従ってOKですが、またはそれは、コンパイラの許容範囲でしょうか?

+0

をまあ、私は、たとえば、あなたが持つことを許さている知っている '無効のfoo(){}空のバー(){リターンのfoo();}'。私はこれについては分かりません。 – chris

+1

具体的にあなたの質問は何ですか?戻り値 'void'について(BTWはいつもC++では合法です)?あるいは 'constexpr void'の組み合わせについて? – AnT

+3

エラーがどのようになるはずと思いますか? –

答えて

24

これは段落は(強調鉱山を)言うdraft C++11 standard、我々はセクションを見れば5.2.3明示的な型変換(関数表記)によって有効になります。

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of type T; no initialization is done for the void() case.[...]

文言はかなり似ていますpre C++11も同様である。

The definition of a constexpr function shall satisfy the following constraints:

と、この弾丸を含んを:

its return type shall be a literal type;

のボイドリテラルない部分7.1.5段落3が言うにもかかわらず、constexprの

これ大丈夫C++ 11セクションごと3.9段落、しかし我々は、それがこのケースに合った例外を与える段落を見れば、それは言う:C++14 draft standard無効でケーシーnotedよう

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member function it will still be const as described below. —end note ] If no specialization of the template would yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.

はリテラルです、このセクションで3.9タイプ段落は言う:

A type is a literal type if it is:

と含まれています

— void; or

6

詳細については、@ Shafik Yaghmourの答えをご覧ください。

以下の段落は、非テンプレート(7.1.5(3))のためにこれを禁止:

The definition of a constexpr function shall satisfy the following constraints:

  • [...]

  • its return type shall be a literal type or a reference to literal type

詳述すると、リテラル型がスカラー型または組成物として3.9(10)で定義されています配列または構造体のリテラル型オブジェクトvoidは3.9(9)でスカラー型ではありません。

+1

*リテラルタイプ*は3.9/10で定義されています。 'void'はC++ 11のリテラル型ではありません。しかし、C++ 14(N3797)では、 'void' *がリテラル型に含まれています。したがってOPのコードはC++ 14に準拠します。 – Casey

+2

@Caseyまた、私は7.1.5段落6がC++ 11でこれを可能にすると思う。 –

+1

@ShafikYaghmourああ、私は同意する。面白いことに、このコードは、C++ 11では 'const '、' const'メンバ関数、C++では 'constexpr'と非' const'メンバ関数に特化しています! – Casey

1

あなたの関数はvoid()という値を返します。あなた自身がvoid関数から返ってくるわけではありません。 NULLの値が返されます。あなたがやっていることは次のようになります:

void f() { return void(); } 

これは唯一の空値である空値を返します。空の関数から別の型を返すことはできません。

+0

私はこれがC++で5.2.3(2)で許可されていると確信していますが、IANALLです。 – filmor

+0

これはコンパイラによって許可されていますが、値を持たないため実際には有用ではありません。 – user3084096

+2

これは、言語基準について話すときのポイントではありません。 – filmor

関連する問題