2

Typedef declarations can, whereas alias declarations cannot, be used as initialization statements?

The grammar for an init-statement is, for C++17, as follows:

init-statement:

expression-statement:

  • expression_opt;

simple-declaration:

  • decl-specifier-seq init-declarator-list_opt ;
  • attribute-specifier-seq decl-specifier-seq init-declarator-list ;
  • attribute-specifier-seq_opt decl-specifier-seq ref-qualifier_opt [ identifier-list ] initializer ;

[...]

A typedef declaration may be used as an init-statement, and e.g. the following is valid (C++17) code:

if (typedef int Foo; true) { (void)Foo{}; }
//  ^^^^^^^^^^^^^^^ init-statement

switch(typedef int Foo; 0) { case 0: (void)Foo{}; }
//     ^^^^^^^^^^^^^^^ init-statement

whereas an alias-declaration may not be used as an init-statement:

if (using Foo = int; true) { (void)Foo{}; }
//  ^^^^^^^^^^^^^^^ error: expected expression

switch(using Foo = int; 0) { case 0: (void)Foo{}; }
//     ^^^^^^^^^^^^^^^ error: expected expression

Afaics a typedef declaration is a valid simple-declaration as typedef is a decl-specifier which is part of a decl-specified-seq which in turn, by itself, is a valid simple-declaration, whereas an alias-declaration is an entirely different declaration and not a simple-declaration.

Much like the answers in What is the difference between 'typedef' and 'using' in C++11?, I was always under the impression that alias declarations have the same semantics as and never falls short of typedef declarations, but as is apparent by the examples above (as of C++17?) it does, in use cases restricted to simple-declaration:s, particularly C++17 initialization statements (init-statement:s).

Question:

  • Is it indeed a fact that a typedef declaration is a valid init-statement/simple-declaration whereas an alias declaration is not? Is this an intended "deviation" as of C++17 w.r.t. the previous (near-?)identical semantics of these two types of declarations?
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 3
    I'm not sure we can call the semantics the same previously either. `for(typedef int Foo ; ;)` is valid since C++03, but the alias declaration was never valid in this location either. It's the same thing. Honestly, I think it's just not something anyone was ever bothered about, or thought should be made equivalent. – StoryTeller - Unslander Monica Jun 03 '20 at 15:24
  • @StoryTeller-UnslanderMonica Ah that is true (as of C++11, as we only had the typedef declaration in C++03). Maybe it's just as simple as that; a non-important corner case. I've never considered ever using a typedef declaration in a `for(...)` statement, though, whereas using a typedef in an init expression in e.g. `if` statements could arguably (or arguably not? :) ) come in handy in some situations. – dfrib Jun 03 '20 at 15:27

1 Answers1

0

Is it indeed a fact that a typedef declaration is a valid init-statement/simple-declaration whereas an alias declaration is not

Yes, a typedef declaration is a valid init-statement, whereas an alias declaration is not.

Is this an intended "deviation" as of C++17 w.r.t. the previous (near-?)identical semantics of these two types of declarations?

As noted in @StoryTeller's comment, this was not just the case with the expanded contexts of init-statement:s in C++17 (adding them to e.g. if and switch statements), but already present since C++03 and a difference between typedef declarations and alias declarations from the start of the introduction of alias declarations in C++11:

// C++11 (C++03) (init. statement in for loop iteration statements).
for(typedef int Foo; Foo{} != 0;) {}
//  ^^^^^^^^^^^^^^^ init-statement

// C++ 11.
for(using Foo = int; Foo{} != 0;) {}
//  ^^^^^^^^^^^^^^^ error: expected expression
dfrib
  • 70,367
  • 12
  • 127
  • 192