7

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)。就这样吧。

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

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();
}

So well, enough examples. Anyone can help me get around this without making anything too anti-idiomatic (I'm a library developer, and people like idiomatic libraries)?

-- edit

Never mind. This is a dupe of Most vexing parse: why doesn't A a(()); work?.

Thanks, sbi.

4

3 回答 3

6

This is known as "C++'s most vexing parse". See here and here.

于 2010-02-16T19:31:17.140 回答
1

Based on the "C++0x allowed", the right answer is (probably) to change the definition to:

Class c(ArgType {});

Simple, straightforward and puts the burden entirely on the user of the library, not the author!

Edit: Yes, the ctor is invoked -- C++ 0x adds List-Initialization as an unambiguous way to delimit initializer lists. It can't be mis-parsed like in your sample, but otherwise the meaning is roughly the same as if you used parentheses. See N3000, the third bullet point under §8.5.4/3. You can write a ctor to receive an initializer list as a single argument, or the items in the initializer list can be matched up with the ctor arguments individually.

于 2010-02-16T19:38:04.563 回答
1

Let's simplify a little.

int f1();

What's that? The compiler (and I) say it's a forward declaration for a function returning an integer.

How about this?

int f2(double );

The compiler (and I) say it's a forward declaration for a function taking a double argument and returning an int.

So have you tried this:

ClassType c = ClassType(ArgType());

Check out the c++ faq lite on constructors for explanations and examples

于 2010-02-16T19:41:32.233 回答