0

I was making a class that looked like this:

struct InputHandler
{
    std::vector<std::pair<int, int>> keyBindings( 256 );
};

It came up with an error, and I know this is because the compiler interprets this as a function instead of a constructor argument. But I was wondering is there anything ambiguous when I've passed a number literal in brackets such as in this case? I know I can fix this by just using curly brackets here, but I would have thought the most vexing parse issue wouldn't arise as using a number literal of 256 couldn't be interpreted as a function.

Edit: I'm happy to close or delete this question. The thing I learned is that even though that particular line isn't ambiguous, the general rules of C++11 forbid in-class initialisers with anything other than = or {}, this is as a general rule so as not to have an extra exception to the rule. On the other hand creating the vector in the main() function as:

std::vector<std::pair<int, int> foo(5);

Works fine. It's not an ambiguous expression, apparently.

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • "The compiler" doesn't interpret this as function declaration. It just isn't allowed syntax. – juanchopanza Jan 01 '18 at 08:24
  • The duplicate question says that it's because it's an ambiguity, in my case it's not ambiguous, which is why I asked why it wouldn't be accepted. I tried to delete my question but it wouldn't let me, saying that people have invested time in answering it, so I'll just accept the answer. It seems it's not ambiguous but the rules are consistent so as to not add another exception to the rule. – Zebrafish Jan 01 '18 at 08:31
  • 1
    @Zebrafish Right, the rules are there to avoid the possibility of ambiguity, i.e. to not replicate the most vexing parse fiasco. – juanchopanza Jan 01 '18 at 08:43

2 Answers2

4

but I would have thought the most vexing parse issue wouldn't arise as using a number literal of 256 couldn't be interpreted as a function.

That is correct, it is not the most vexing parse. The most vexing parse is formally handled in [dcl.ambig.res]:

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct that could possibly be a declaration a declaration.

The catch here is that you cannot initialize members using (), only = or {}, so naturally the ambiguity resolution does not apply.

2

But I was wondering is there anything ambiguous when I've passed a number literal in brackets such as in this case?

Probably not, but it would have made the grammar more complex. Default member initializers were made to support only uniform initialization and copy initialization, because those things couldn't have appeared in existing code. And differentiating them from function declarations is easy.

Adding another overloaded usage for parentheses was never a goal. It's overused as is, IMO. If it's not supported in general, supporting it just for this particular use case you have in mind is hardly a useful feature that would merit the grammar contortions.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I hope you don't mind me accepting the other answer instead of yours. That answer emphasises that this is only the case for in-class initialisers, and that these only accept = or {}. I tested by doing the same thing in my main class and it compiled fine by calling the instructor instead of disallowing () initialisation, so it seems correct. Thanks. – Zebrafish Jan 01 '18 at 08:45
  • @Zebrafish Careful with `std::vector> keyBindings{256};` though! It is the new thing you have to think about now that you don't have think about the most vexing parse :-) – juanchopanza Jan 01 '18 at 08:59