Anonymous object with one argument cannot be declared

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

      

The anonymous object SomeClass with 0 and 2 parameters can be declared, however it cannot be declared with only one argument. I assume that the entry

SomeClass(a);

      

coincides with

SomeClass a;

      

How do I create an anonymous object with one argument?

+3


source to share


5 answers


You can create a temporary object in your own statement with something like:

(SomeClass)a;

      

or



(SomeClass(a));

      

As you noticed, parentheses are necessary to disambiguate between a declaration and an expression.

+3


source


You can create this anonymouse object like this:

(SomeClass(a));

      



This removes the ambiguity as it cannot be a declaration a

.

(SomeClass a); // Error: this can't be a declaration because of the parentheses
               //        but what else should it be?

      

+2


source


In this context, the parentheses are superfluous, which means

SomeClass(a); //declaration of a

      

is exactly equivalent to

SomeClass a; //declaration of a

      

which again is equivalent to these:

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

      

They all declare a name variable a

and type SomeClass

.

+2


source


In general, you avoid the most annoying parsing by writing code with the same effect as what you wanted to write, but it cannot be parsed as a declaration.

This is often done by adding parentheses.

In this case, (SomeClass(a));

will do, or(void) SomeClass(a);

+1


source


Your guess is correct.

You simply cannot create a temporary object with a single constructor argument in a context where the same statement can be a declaration. The grammar makes this ambiguous (or, it would be ambiguous if the behavior you see was not defined to take precedence).

Why don't you give the object a name?

SomeClass obj(a);

      

Or, if you have a reason to immediately destroy the object (this is sometimes useful, for example boost::this_thread::interruption_point

, although this takes no arguments), you can still create a temporary but defuse statement:

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

      

In some scenarios, you can also use C-style casts:

(SomeClass)a;

      

But hopefully your constructor SomeClass

is actually marked explicit

and we prefer not to use C-style casts anyway.

This problem does not arise in other contexts where temporal might make more sense:

std::cout << SomeClass(a);  // *can't* be a decl of a `SomeClass` called `a`

      

0


source







All Articles