Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
529 views
in Technique[技术] by (71.8m points)

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

#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.不要吐槽代码,这是一道题 :>


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 是一个函数。


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...