对象构造/转发函数声明歧义

时间:2010-02-16 19:22:29

标签: c++ forward-declaration ambiguity object-construction

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.

您好,

我偶然发现了一些我不理解的对象构造语句,并且只是在今天我才注意到它引入的模糊性。我将解释如何重现它,并想知道是否有办法解决它(允许C ++ 0x)。在这里。

假设有一个类,其构造函数只接受一个参数,而这个参数的类型是另一个具有默认构造函数的类。 E.g:

struct ArgType {};

class Class
{
public:
    Class(ArgType arg);
};

如果我尝试在堆栈上构造类型为Class的对象,我会产生歧义:

Class c(ArgType()); // is this an object construction or a forward declaration
                    // of a function "c" returning `Class` and taking a pointer
                    // to a function returning `ArgType` and taking no arguments
                    // as argument? (oh yeh, loli haets awkward syntax in teh
                    // saucecode)

我说这是一个对象构造,但编译器坚持认为它是函数体内的前向声明。对于仍然没有得到它的人来说,这是一个完全有效的例子:

#include <iostream>

struct ArgType {};
struct Class {};

ArgType func()
{
    std::cout << "func()\n";
    return ArgType();
}

int main()
{
    Class c(ArgType());

    c(func); // prints "func()\n"
}

Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works
{
    funcPtr();
    return Class();
}

那么好,足够的例子。任何人都可以帮助我解决这个问题,而不会产生任何过于反本能的东西(我是图书馆开发人员,而且人们喜欢习惯性的图书馆)?

- 编辑

没关系。这是Most vexing parse: why doesn't A a(()); work?的欺骗。

谢谢,sbi。

3 个答案:

答案 0 :(得分:6)

这被称为“C ++最令人烦恼的解析”。请参阅herehere

答案 1 :(得分:1)

基于“C ++ 0x allowed”,正确答案是(可能)将定义更改为:

Class c(ArgType {});

简单,直接,并将负担完全放在库的用户身上,而不是作者!

编辑:是的,调用ctor - C ++ 0x添加List-Initialization作为分隔初始化列表的明确方法。它不能像你的样本那样被错误解析,但其他含义与你使用括号大致相同。见N3000,§8.5.4/ 3下的第三个要点。您可以编写一个ctor来接收初始化列表作为单个参数,或者初始化列表中的项可以单独与ctor参数匹配。

答案 2 :(得分:1)

让我们简化一点。

int f1();
那是什么?编译器(和我)说它是返回整数的函数的前向声明。

这个怎么样?

int f2(double );

编译器(和我)说它是一个带有double参数并返回int的函数的前向声明。

所以你试过这个:

ClassType c = ClassType(ArgType());

查看constructors上的{+ 3}}和示例

上的c ++ faq lite