関数呼び出しパラメータにおけるコンストラクタ形式のキャスト 質問する

関数呼び出しパラメータにおけるコンストラクタ形式のキャスト 質問する

コンストラクター スタイルのキャストを使用すると、次のコードがコンパイルに失敗する理由がわかりません。

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char(0));
}

エラーは次のとおりです:

  • error: expected primary-expression before ‘unsigned’gcc の場合。
  • error: expected '(' for function-style cast or type construction鳴らす

ただし、次の 3 つの構文は正しいです。

template<typename T> void foo(const T& t){}

int main(){
  // c-style cast
  foo((unsigned char)0);

  // without unsigned
  foo(char(0));

  // aliased unsigned char
  typedef unsigned char uchar;
  foo(uchar(0));
}

したがって、ここでは明らかに、文字内のスペースに問題があることがわかります。

昔の友達と関係があるのか​​なと思った最も厄介な解析なので、統一された初期化構文、これはこの種の曖昧さを解消するはずですが、うまくいきませんでした。

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char{0});
}

それでも:

  • error: expected primary-expression before ‘unsigned’gcc の場合。
  • error: expected '(' for function-style cast or type construction鳴らす

そこで私の質問は、関数スタイルのキャストでスペースを含む型を持つことがなぜ許可されないのかということです。私には曖昧には見えません。

注記: 書けるのは分かっていますfoo<unsigned char>(0)が、質問の答えにはなりません ;)

ベストアンサー1

[C++11: 5.2.3/1]:単純型指定子(7.1.6.2)または型名指定子(14.6)の後に括弧で囲まれた表現リスト式リストを指定して指定された型の値を構築します。[..]

文法を調べてみるとunsigned char単純型指定子生成は、これら 2 つを連結することによって行われます。

表 10 がそれと反対のことを述べているという噂を覆す証拠として、私自身が少し前に言い始めたかもしれませんが (:P)、表の見出しには「指定子」(オプションの複数形に注意) とあり、以下の文章を参照してください。

[C++11: 5.2.3/2]: [..]表10は有効な組み合わせ単純な型指定子およびそれらが指定するタイプ。(強調は筆者による)

さて、組み合わせると単純な型指定子いくつかのケースでは許可されます:

[C++11: 7.1.6.2/3]:複数の単純な型指定子許可されている場合、他のものと自由に混合できます宣言指定子順序は問いません。[..]

…しかし、関数記法ではこれが当てはまらないという兆候は見られません。関数記法では明確に「1つの 単純型指定子" - 特異な。

したがって、GCC は正しく、Visual Studio は間違っています。

はどうかと言うとなぜこれは... まあ、わかりません。曖昧なエッジケースを思いつくことはできると思いますが、ケーシー下記のコメントでは、関数名にスペースを含めることはできないため、これを許可すると関数呼び出し構文と矛盾するという適切な指摘があります。

おすすめ記事