4

Sample code:

typedef int I;
struct X{ X(int); };

int main()
{
    int(int());
    X(X());
    I(I());
}

The line int(int()); is an expression using functional cast notation - it's a temporary int initialized with a value-initialized int.

The line X(X()); is a declaration of a function named X taking no arguments returning struct X.

My question is: what is the meaning of I(I()) here? And what rules in the standard determine the difference in meaning between these three cases?

M.M
  • 138,810
  • 21
  • 208
  • 365
  • 1
    The `typedef int I` makes `I` behave *exactly* like `int`. It merely assigns another name. Therefore the line `I(I())` and `int(int())` have the exact same meaning. For more on `typedef` see [[dcl.typedef](https://timsong-cpp.github.io/cppwp/dcl.typedef)]. – Henri Menke Aug 04 '17 at 00:20
  • According to gcc/clang, it is as for `X`, a declaration of function `I` returning `int`. – Jarod42 Aug 04 '17 at 00:21
  • 1
    all 3 are function decls – Sopel Aug 04 '17 at 00:22
  • 1
    @Sopel: False. As it is clearly stated in the question, the first one is NOT a function declaration. The fact that `int` is a keyword makes a critical difference in the first case. – AnT stands with Russia Aug 04 '17 at 00:23
  • whoops, sorry, there are no names, you're right – Sopel Aug 04 '17 at 00:24
  • I would say that `int` is not a valid name for function contrary to `X`/`I`. – Jarod42 Aug 04 '17 at 00:25

1 Answers1

3

The rule says that if a construct is ambiguously syntax for either a declaration, or a statement, then it is considered to be a declaration.

[stmt.ambig] 1 There is an ambiguity in the grammar involving expression-statements and declarations: An expression- statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indis- tinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

X(X()); is ambiguous, because it could be either a cast, or a function declaration, so it is considered to be a declaration.

int(int()); cannot be a function declaration, because int, being a keyword, is not a valid name for a function. So, there is no ambiguity, it is a cast.

Likewise, I(I()); cannot be a function declaration, because although not a keyword, I is not a valid name either because it would redeclare the type I as a function, which is not allowed, so it is a cast.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • What are you saying `I(I());` means then exactly? – M.M Aug 04 '17 at 00:53
  • @M.M As I understand the rules, It is a functional cast, and value initialized temporary, as is `int(int())`. – eerorika Aug 04 '17 at 00:58
  • This *might* be the rule that disallows re-definition of a typedef: `A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration,typedef-name is syntactically equivalent to a keyword and ...`. Keywords may not be re-defined... but this seems a bit vague. – eerorika Aug 04 '17 at 01:04
  • 1
    The rule is this one: http://eel.is/c++draft/basic.scope.declarative#4 It only applies if the typedef is in the same declarative region as the other declaration. Not if one of them is in a nested scope. The purpose of this rule is to disallow this kind of silliness as much as possible, only retaining compatibility with C (which, e.g., has both a function and a struct named `stat`) – Brian Bi Aug 04 '17 at 01:24