为什么以下代码是一句函数声明而不是变量创建?

#include <iostream>
#include <string>
using namespace std;

struct Print {
    template<typename T>
    Print(T t){
        cout<<(t+=10);
    }
};

int main()
{
    // 这句为什么是一句函数声明而不是变量创建?
    Print p(string());
    
    return 0;
}

clang++ 10.0.0提示:

`warning: parentheses were disambiguated as a function declaration`

为什么会这样,我觉得string()是创建了一个临时量,这应该是个变量创建才对,为什么编译器会认为是个函数声明呢?

PS.不要吐槽代码,这是一道题 :>

阅读 3k
1 个回答

dcl.ambig.res

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct that could possibly be a declaration a declaration. [ Note: A declaration can be explicitly disambiguated by adding parentheses around the argument. The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast. — end note ] [ Example:

    struct S {
      S(int);
    };

    void foo(double a) {
      S w(int(a));                  // function declaration
      S x(int());                   // function declaration
      S y((int(a)));                // object declaration
      S y((int)a);                  // object declaration
      S z = int(a);                 // object declaration }

— end example ]

An ambiguity can arise from the similarity between a function-style cast and a type-id_. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id_. [ Example:

template <class T> struct X {};
template <int N> struct Y {};
X<int()> a;                     // type-id X<int(1)> b;                    // expression (ill-formed) Y<int()> c;                     // type-id (ill-formed) Y<int(1)> d;                    // expression 
void foo(signed char a) {
  sizeof(int());                // type-id (ill-formed)
  sizeof(int(a));               // expression
  sizeof(int(unsigned(a)));     // type-id (ill-formed) 
  (int())+1;                    // type-id (ill-formed)
  (int(a))+1;                   // expression
  (int(unsigned(a)))+1;         // type-id (ill-formed) }

— end example ]

string()string("str")string(a),在 C++ 语法结构里,都属于 function style cast 。

当 function style cast 与 declaration(声明) 出现出现歧义的时候,认为是 declaration。

当 function style cast 与 type id 出现歧义的时候,认为是 type id

string() 可以被认成一个函数类型(type id),返回值是 string,没有参数,然后由于位于函数参数位置,被当作函数指针使用

string() 认为是 function style cast,那么 Print p(string()) 是变量声明。

string() 认为是 type id ,那么 Print p(string()) 是一个函数。(想想 Print p(int)int 也是一个 type id)

两者均合法,有歧义,认为 string() 是 type id ,p 是一个函数。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏