89

For example a declaration such as that:

int (x) = 0;

Or even that:

int (((x))) = 0;

I stumbled upon this because in my code I happened to have a fragment similar to the following one:

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

Obviously I wanted to construct object C which then would do something useful in its destructor. However as it happens compiler treats C (y); as a declaration of variable y with type C and thus it prints an error about y redefinition. Interesting thing is that if I write it as C (y).f () or as something like C (static_cast<B*> (y)) it will compile as intended. The best modern workaround is to use {} in constructor call, of course.

So as I figured out after that, it's possible to declare variables like int (x) = 0; or even int (((x))) = 0; but I've never seen anyone actually using declarations like this. So I'm interested -what's the purpose of such possibility because for now I see that it only creates the case similar to the notorious "most vexing parse" and doesn't add anything useful?

sashoalm
  • 75,001
  • 122
  • 434
  • 781
Predelnik
  • 5,066
  • 2
  • 24
  • 36
  • possible duplicate of [What is the purpose of a declaration like int (x); or int (x) = 10;](http://stackoverflow.com/questions/26832321/what-is-the-purpose-of-a-declaration-like-int-x-or-int-x-10) – GSerg Apr 16 '15 at 17:14
  • 1
    @GSerg Funny how the text of my question answers to the question from the second answer in your linked question, since I provide the example where allowing such declarations leads to unexpected results :) – Predelnik Apr 16 '15 at 18:42
  • http://stackoverflow.com/questions/6341951/whats-actually-going-on-in-this-anonymousclassvariable-declaration – jamesdlin Apr 17 '15 at 07:18
  • walked into this trap: didnt know mutex was commented out and then accidently wrote the incorrect parenthesis declaration. //std::mutex std::unique_lock(m_mutex); – Serve Laurijssen Nov 27 '18 at 10:26

2 Answers2

86

Grouping.

As a particular example, consider that you can declare a variable of function type such as

int f(int);

Now, how would you declare a pointer to such a thing?

int *f(int);

Nope, doesn't work! This is interpreted as a function returning int*. You need to add in the parentheses to make it parse the right way:

int (*f)(int);

The same deal with arrays:

int *x[5];   // array of five int*
int (*x)[5]; // pointer to array of five int
  • 14
    And to complete the answer: disallowing the particular case that the asker is asking about would require an extra special-case rule. The current definition of how `()` work in a type is uniform throughout the type. – Joseph Mansfield Apr 16 '15 at 13:14
  • So the special-case applies to the most-vexing parse. This is because the syntax for initializing variables with constructor arguments was added later (in a hurry I guess?). – AnArrayOfFunctions Apr 16 '15 at 14:22
  • 1
    @FISOCPP Well. . yes. C++ came after C. . . – iheanyi Apr 16 '15 at 17:06
  • Does this answer equally apply to C, not just C++? – kdbanman Apr 29 '15 at 13:27
  • "_variable of function type_" what?!! – curiousguy Oct 07 '15 at 02:47
  • @AnArrayOfFunctions This is why C++ parser is a much more complicated than a C one - `x(y) = z` could be either a variable definition with initialization or a call to a constructor that returns an object with `=` or a call to a function that returns a reference that is assigned to or... – Antti Haapala -- Слава Україні Aug 26 '17 at 07:10
  • @curiousguy Functions are first-class objects... except that they're not objects. – wizzwizz4 Dec 12 '17 at 18:27
  • @AnttiHaapala Note that although `x(y) = z` cannot be well formed expression in C, it's still grammatically an expression if all 3 names are valid expressions (if they are either function names or variable names). It doesn't matter at that point that `x(y)` is always a rvalue in C. – curiousguy Dec 13 '17 at 03:33
17

There's generally allowed to use parentheses in such declarations because the declaration, from the syntactical point of view looks always like this:

<front type> <specification>;

For example, in the following declaration:

int* p[2];

The "front type" is int (not int*) and the "specification" is * p[2].

The rule is that you can use any number of parentheses as needed in the "specification" part because they are sometimes inevitable to disambiguate. For example:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints

The pointer to an array is a rare case, however the same situation you have with a pointer to function:

int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int

This is the direct answer to your question. If your question is about the statement like C(y), then:

  • Put parentheses around the whole expression - (C(y)) and you'll get what you wanted
  • This statement does nothing but creating a temporary object, which ceases to living after this instruction ends (I hope this is what you intended to do).
T.C.
  • 133,968
  • 17
  • 288
  • 421
Ethouris
  • 1,791
  • 13
  • 18
  • 1
    As I mentioned, initially it was doing something in destructor, I guess it's pretty standard thing when you have some number of "chaining" functions for setting some parameters and then doing all the job in the destructor. Thanks for one more workaround though, I guess writing `{}` is the most valid one after all. – Predelnik Apr 16 '15 at 13:27
  • 4
    try to avoid making up your own grammar and use the one provided in the standard. ` ` is misleading, and wrong. The grammar is ` ` – Steve Cox Apr 16 '15 at 17:07
  • You're right - I didn't look into the standard, just repeated the rule from my head. Actually in C++11 the role of `` can be also played by `auto` keyword, so it's not even always a type. – Ethouris Apr 17 '15 at 11:11
  • @Pravasi Meet: If you have edited the part of my post and changed names in the given syntax schema, please change the names 3 lines below accordingly as well. Otherwise there are still old names "front type" and "specification" and therefore the post doesn't make any sense. – Ethouris Jul 15 '15 at 09:17