38

If you look at the grammar for *declarator*s in §8/4 you'll notice that a noptr-declarator can be written as (ptr-declarator), that is, it can be written as (declarator-id), which validates declarations like the ones in the title. As matter of fact this code compiles without a problem:

#include <iostream>
struct A{ int i;};
int (x) = 100;
A (a) = {2};
int main()
{
    std::cout << x << '\n';
    std::cout << a.i << '\n';
}

But what is the purpose of allowing these parentheses when a pointer (to an array or to a function) is not involved in the declaration?

Syeda Zunaira
  • 5,191
  • 3
  • 38
  • 70
Mao
  • 1,065
  • 8
  • 12

2 Answers2

51

The fact that this rule is applicable in your case is not deliberate: It's ultimately a result of keeping the grammar simple. There is no incentive to prohibit declarations such as yours, but there are great disincentives to complicate rules, especially if those are intricate as they are.

In short, if you don't want to use this needlessly obfuscated syntax, don't.
C++ rarely forces you to write readable code.

Surprisingly there are scenarios in which parentheses can save the day, though:

std::string foo();

namespace detail
{
    int foo(long); // Another foo

    struct Bar
    {
        friend std::string ::foo(); // Doesn't compile for obvious reasons.

        friend std::string (::foo)(); // Voilà!
    };
}
Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Couldn't you give a little explaination about `friend std::string (::foo)();` declaration? What did we actually declare and why? –  Apr 17 '15 at 05:33
  • 5
    @DmitryFucintv: The declaration wants to declare the instance of `foo` that is declared in the first line to be a `friend` of the struct `Bar`. To declare a function to be friend, you need to give its return type and arguments. But saying `friend std::string foo()` won't work, since for unqualified use, that `foo` is hidden by 'another' `foo`. So one must qualify `foo` by the global qualifier `::`. But that gives the first form displayed, which suffers from ambiguity with designation of a (non-existent) member of `std::string`. A pair of parentheses around `::foo` serves to avoid the ambiguity – Marc van Leeuwen Apr 17 '15 at 07:39
4

You're asking the wrong question. The correct question is:

What is the purpose of disallowing such a declaration?

The answer is: there is none.

So, given that this syntax is allowed as a side-effect of rules elsewhere, this is what you get.

Columbo
  • 60,038
  • 8
  • 155
  • 203
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    One reason to disallow such a declaration is that at present the statement `T(x);` is the declaration of a variable `x` of type `T`, rather than a functional cast expression of `x` to type `T` (done purely for its side-effects), which is what it looks like. – jchl Jan 22 '18 at 14:01
  • @jchl: _"done purely for its side-effects"_ There's your problem – Lightness Races in Orbit Jan 22 '18 at 18:02