9

ptr2基本的に、コンパイラが宣言を拒否する理由を知りたいです。

int main() {
    // this one works
    decltype(void())* ptr1;

    // this one does not
    decltype(void{})* ptr2;
}

関数ポインタだと思われる場合は、次のコードを見てください。ptr1

#include <iostream>
using namespace std;

template <class T>
void f(T t) {
    cout << __PRETTY_FUNCTION__ << endl;
}

int main() {
    decltype(void())* ptr;
    f(ptr);
}

出力はvoid f(T) [with T = void*]です。

4

1 に答える 1

11

[expr.type.conv]

2 式は、非配列完全オブジェクト型または (おそらく cv 修飾された) 型のT()単純型指定子または型名指定であり、指定された型の prvalue を作成します。その値は value- によって生成されたものです。タイプのオブジェクトを初期化(8.5)します。ケースの初期化は行われません。[...]TvoidTvoid()

NBvoid simple-type-specifierです。

3 同様に、 braced -init-listが後に続くsimple-type-specifierまたはtypename-specifierは、指定された braced -init-listを使用して、指定された直接リスト初期化型 (8.5.4) の一時オブジェクトを作成し、そのvalue は、prvalue としてのその一時オブジェクトです。

一時オブジェクトは /3 で作成され、は /2 で作成されることを指摘してくれたKeith Thompsonに感謝します。

[basic.types]/5 を見ると

不完全に定義されたオブジェクト型であり、そのvoid型は不完全な型です (3.9.1)。オブジェクトは、不完全な型を持つように定義されてはなりません。

void{}(一時的な)オブジェクトを作成するため、許可されていないことが明らかになりました。void()ただし、「のみ」は (pr) 値を作成します。これら 2 つのケースの実装 (動作) に違いはないと思いますが、異なる言語ルールが適用されます。これらの規則の 1 つは、 type のオブジェクトの作成を禁止しているvoidため、エラーが発生します。


Ad decltype(void()):decltype(e)式を取りますe。[dcl.type.simple]/4 では、適用可能な定義decltype(e)は次のとおりです。

それ以外の場合decltype(e)は、のタイプですe

( asvoid()は prvalue を生成し、id-expressionではありません)。

したがって、decltype(void())が得られvoidます。

于 2013-09-22T21:52:37.273 に答える