3

There is this code:

class SomeClass
{
public:
    SomeClass(){}

    SomeClass(SomeClass& b){}

    SomeClass(SomeClass&b, SomeClass& c){}
};

int main()
{
    SomeClass a;
    SomeClass(); // works all right
    //SomeClass(a); error: redeclaration of ‘SomeClass a’
    SomeClass(a, a); // works all right
    return 0;
}

Anonymous object of SomeClass with 0 and 2 parameters can be declared, however it cannot be declared with only 1 argument. I assume that writing

SomeClass(a);

is the same as

SomeClass a;

How to create anonymous object with one argument?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
scdmb
  • 15,091
  • 21
  • 85
  • 128
  • @BoBTFish: No. He is creating a temporary object through functional-cast syntax, essentially. You _never_ call a constructor directly; not even the code you posted actually does that – Lightness Races in Orbit Mar 20 '12 at 16:21
  • possible duplicate of [What's actually going on in this AnonymousClass(variable) declaration?](http://stackoverflow.com/questions/6341951/whats-actually-going-on-in-this-anonymousclassvariable-declaration) – Nawaz Mar 20 '12 at 16:31

5 Answers5

3

You can construct a temporary object in a statement of its own with something like:

(SomeClass)a;

or

(SomeClass(a));

As you've observed, the parentheses are needed to resolve the ambiguity between a declaration and an expression statement.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
2

You can create that anonymouse object as the following:

(SomeClass(a));

This resolves the ambiguity since it can't be a declaration of a.

(SomeClass a); // Error: this can't be a declaration because of the parentheses
               //        but what else should it be?
ipc
  • 8,045
  • 29
  • 33
2

In that context, the braces are superfluous, which means

SomeClass(a); //declaration of a

is exactly equivalent to

SomeClass a; //declaration of a

which is again equivalent to these:

SomeClass((a)));       //declaration of a
SomeClass(((a)));      //declaration of a
SomeClass((((a))));    //declaration of a
SomeClass(((((a)))));  //declaration of a

All of these declare a variable of name a and type SomeClass.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

In general, you avoid the most vexing parse by writing code with the same effect as what you wanted to write, but that can't be parsed as a declaration.

Often, this is done by adding parentheses.

In this case (SomeClass(a)); will do, or (void) SomeClass(a);

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
0

Your assumption is correct.

You simply cannot create a temporary object with a single constructor argument in a context where the same statement could be a declaration. The grammar makes it ambiguous (or, it would be ambiguous if the behaviour you're seeing weren't defined to take precedence).

Why not give the object a name, instead?

SomeClass obj(a);

Or, if you have a reason to want the object to be destroyed immediately (sometimes this is useful; e.g. a boost::this_thread::interruption_point, though that takes no arguments), you can still create a temporary but de-ambiguate the statement:

(SomeClass(a));    // the parens prevent this from being a declarative statement

In some scenarios you may also be able to use C-style casts:

(SomeClass)a;

But, hopefully, your SomeClass constructor is actually marked explicit, and we prefer not to use C-style casts anyway.

This problem doesn't arise in other contexts, ones in which a temporary might make more sense anyway:

std::cout << SomeClass(a);  // *can't* be a decl of a `SomeClass` called `a`
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055