7

Trying to compile:

class AnonymousClass
{
public:
    AnonymousClass(int x)
    {
    }
};


int main()
{
    int x;
    AnonymousClass(x);
    return 0;
} 

generates errors from MSVC:

foo.cpp(13) : error C2371: 'x' : redefinition; different basic types
    foo.cpp(12) : see declaration of 'x'
foo.cpp(13) : error C2512: 'AnonymousClass' : no appropriate default constructor available

g++'s error messages are similar:

foo.cpp: In function ‘int main()’:
foo.cpp:13: error: conflicting declaration ‘AnonymousClass x’
foo.cpp:12: error: ‘x’ has a previous declaration as ‘int x’
foo.cpp:12: warning: unused variable ‘x’

It's easily fixable by giving the AnonymousClass object an explicit name, but what's going on here and why? I presume that this is more declaration syntax weirdness (like the cases described in Q10.2 and Q10.21 of the comp.lang.C++ FAQ), but I'm not familiar with this one.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • 1
    one of the similar questions: http://stackoverflow.com/questions/5159438/strange-compiler-error-when-trying-to-create-a-temporary-object – Cubbi Jun 14 '11 at 10:12
  • Ah, yes, parentheses clearly are legitimate around the symbol name as in the typical case of function pointer declarations. Yay. – jamesdlin Jun 14 '11 at 10:15
  • 1
    You can also prevent `AnonymousClass(x)` from being treated as a definition of `x` by forcing it to be a sub-expression. For example `(void) AnonymousClass(x);`. Syntactically there's no way this can be a definition, hence it's an expression statement that creates an object using the one-arg constructor then destroys it. – Steve Jessop Jun 14 '11 at 10:51
  • Related: https://stackoverflow.com/questions/24155571/how-is-atmpvector-the-same-as-a-tmpvector – jamesdlin Oct 03 '19 at 05:24

3 Answers3

10
AnonymousClass(x);

It defines a variable x of type AnonymousClass. That is why you're getting redefinition error, because x is already declared as int.

The parentheses are superfluous. You can add even more braces like:

AnonymousClass(x);
AnonymousClass((x));
AnonymousClass(((x)));
AnonymousClass((((x))));
//and so on

All of them are same as:

AnonymousClass x;

Demo: http://www.ideone.com/QnRKH


You can use the syntax A(x) to create anonymous object, especially when calling a function:

int x = 10;
f(A(x));        //1 - () is needed
f(A((((x)))));  //2 - extra () are superfluous

Both line 1 and 2 call a function f passing an object of type A :

But again, the extra parentheses are still superfluous at line 2.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Okay, thanks. Is allowing parentheses around declared names useful for anything other than for declaring function pointers? – jamesdlin Jun 14 '11 at 10:25
  • @jamesdlin: As I said, parentheses are *superfluous* when declaring a variable. But they're NOT *superfluous* when declaring function pointers; its needed then. `A (*x)()` has different meaning than `A *x()`. The former declares a function pointer, latter is a function declaration (prototype). – Nawaz Jun 14 '11 at 10:29
  • @Nawaz: My comment above asked if they're useful for anything *other* than for function pointers. – jamesdlin Jun 14 '11 at 10:32
  • @jamesdlin: I think, the word *superfluous* explains that its not useful when declaring a variable. On the contrary, it adds confusion. – Nawaz Jun 14 '11 at 10:33
  • But they're not completely superfluous. They're superfluous in my particular case, but as you mentioned, they're *not* superfluous for variables of function pointer type. Are there any other cases? It seems a little odd that the C standards committee allowed this weird syntax just for that one case. – jamesdlin Jun 14 '11 at 10:36
  • @jamesdlin: But of course, you can use the syntax `A(x)` to create anonymous object, especially when calling a function: `f(A(x))` and `f(A((x)))` both call `void f(A a);` passing an object of type `A` : http://www.ideone.com/ofbpR – Nawaz Jun 14 '11 at 10:38
  • 5
    @jamesdlin: the parens are also used for declaring array references and pointers. For example `AnonymousClass *ptr[3]` has a different type from `AnonymousClass (*ptr)[3]`. It's really not a case of allowing weird syntax for a special case -- there's a general syntax that happens to be weird with simple types (because it appears ambiguous with what it would mean in an expression, i.e. the construction of a temporary with 1 arg). – Steve Jessop Jun 14 '11 at 10:44
  • @Steve: +1. How come I forgot that. Thanks :-) – Nawaz Jun 14 '11 at 10:45
3

You're missing an actual name for your variable/object:

AnonymousClass myclass(x);

Instead of that you could as well write...

AnonymousClass (myclass)(x);

So your line of code results in this:

AnonymousClass (x);

Or more common:

AnonymousClass x;

Why it happens? Brackets are just there for logical grouping ("what belongs together?"). The only difference is, they're forced for arguments (i.e. you can't just write AnonymousClass myclass x).

Mario
  • 35,726
  • 5
  • 62
  • 78
  • They're more than just for grouping. You can't just add parentheses willy-nilly. Parentheses around types and parentheses with keywords have special meanings. You can't add parentheses around keywords themselves and so forth. Really I wanted to know why parentheses are allowed at all around the variable name in a declaration. – jamesdlin Jun 14 '11 at 10:21
  • Adding parentheses around types is different cause this will be interpreted as a cast. Around keywords they won't make any sense, but around actual (variable names) they make sense for logical grouping (see Nawaz' answer; e.g. telling the compiler where the `*` belongs to). – Mario Jun 14 '11 at 10:40
0

To avoid such a mistake, just remember one rule: If you declare an anonymous object with one argument, just place it into a pair of parentheses!

xmllmx
  • 39,765
  • 26
  • 162
  • 323