4

这不是最令人烦恼的解析的重复:为什么不 A a(()); 工作?,它基于 形式的解析A a(());,其 OP 认为能够A使用额外的括号集默认构造一个对象。

相比之下,我的问题是关于 2 个类,f并且g,哪里f有一个默认构造函数,而gctor 需要一个f. 我想g用一个临时参数调用 ctor f,所有这些都没有使用统一的初始化语法。的 ctor 中有一条std::cout语句g,因此缺少输出表示函数声明而不是g对象实例化。我在注释中用 3 个数字注释了示例代码。#1 和 #2 编译时将 #3 注释掉,反之亦然:

#include <iostream>
struct f {};
struct g {
    g(f) { std::cout << "g's ctor\n"; }
};
int main() {
                          // -----Output-----
    g( f() );             // #1: function declaration; expected
    g( ( f() ) );         // #2: also a function declaration; UNEXPECTED
    // g myG( ( f() ) );  // #3: "g's ctor" ONLY if #1 & #2 are commented out;
                          //     ^ ... linker error otherwise
}

#1:我认为 #1 声明了一个匿名函数,该函数返回 ag并接受一个指向函数的指针,该函数接受 0 个参数并返回一个f. 我错了吗?

#2:所以,我认为 #2 中额外的一组括号将强制将封闭的内容作为函数调用进行评估,即对f的默认 ctor 的调用。但它仍然是一个函数声明。为什么?

#3:是 #2 的变体,区别在于 #3 添加了实例名称myG。如果 #1 和 #2 被注释掉,#3 将实例化对象。否则我会在 VC12 中得到这些错误:

error LNK2019: unresolved external symbol "struct g __cdecl f(void)" (?f@@YA?AUg@@XZ) referenced in function _main

fatal error LNK1120: 1 unresolved externals.

和 g++ 4.8 中的这个错误:undefined reference to 'f()'

它们是什么意思,我为什么要得到它们?

为什么#3只有在实例被命名时才实例化?

如何在不命名实例或使用统一初始化的情况下获得所需的实例化效果?

4

1 回答 1

7

第一个声明了一个调用的函数f,它不带参数并返回g

     g( f() );
  //  ^     ^  redundant set of parentheses

第二个是相同的,还有一组冗余的括号(请记住,您可以根据需要拥有尽可能多的相同函数的声明)。不过,它们并不总是无用的。例如,您需要它们来声明一个返回函数指针的函数:

// function taking an int and returning
// a pointer to a function that takes a char
// and returns a g
g ( *f(int) )(char);
//^         ^ needed, syntax error without them

至于第三个:

当 #1 和 #2 存在时,你有一个 in 的函数声明,f并被main解析g myG( ( f() ) );为一个类型的对象的声明g,命名myG和初始化是函数调用的结果。您收到链接器错误,因为没有f.

当 #1 和 #2 被注释掉时,类型f是可见的,并且用括号消除歧义:

g myG( ( f() ) )
//     ^     ^   these force an expression

没有那对,你会得到另一个函数声明。

你想要的是这样的:

   ( g(f()) );
// ^        ^  must be an expression as declarations can't be parenthesized

或者更少的 Lisp-y: static_cast<g>(f());

于 2013-12-18T01:23:16.950 回答