9

Consider the following code:

int a = 1;
const int& b = a;
std::cout << std::is_same<const decltype(b)&, const int&>();

It compiles on clang 3.5 while GCC 4.9 gives the following error:

error: 'const' qualifiers cannot be applied to 'const int&'

Which one is correct according to the standard? My guess is that GCC is standard-conformant, just as you can't do int& const b = a;.

Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • Which line does make the error ? The `const int& b = a;` or the next one ? – Aracthor Apr 09 '15 at 14:15
  • 3
    FWIW, the cv-qualifiers on a reference are ignored for a *decltype-specifier* in a declaration (see [dcl.ref]). – chris Apr 09 '15 at 14:16
  • `const decltype(b)&` is not the same as `decltype(b)& const` so I don't think your analogy to `int& const` is particularly sound. – Lightness Races in Orbit Apr 09 '15 at 14:19
  • @Aracthor: Why would it be the `const int& b = a` line? – Lightness Races in Orbit Apr 09 '15 at 14:20
  • @Lightning Racis in Obrit: Because the error just says there is a problem with the 'const' of "const int&", and there is a "const in&" on the "const int& b = a" line. – Aracthor Apr 09 '15 at 14:26
  • @LightningRacisinObrit `decltype(b)` is `const int&`. In `const decltype(b)&`, `const` applies to `decltype(b)`, which leads to `const int& const`. So the analogy should be sound. – Lingxi Apr 09 '15 at 14:31
  • @Aracthor, The error says `const` cannot be applied to `const int &` (because it is a reference). The `const` in the second line applies to `int`. – chris Apr 09 '15 at 14:31
  • @Lingxi: _"In const decltype(b)&, const applies to decltype(b)"_ Right, exactly. It does not apply to the `&`, which is the problem in `int& const`. – Lightness Races in Orbit Apr 09 '15 at 14:34

1 Answers1

3

I believe the code is valid and the two types are the same.

[dcl.ref]/1 says:

Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name (7.1.3, 14.1) or decltype-specifier (7.1.6.2), in which case the cv-qualifiers are ignored.

Since you are introducing the first const through a decltype-specifier, it is ignored, and your first type is equivalent to decltype(b)&.

Now [dcl.ref]/6 says:

If a typedef-name (7.1.3, 14.1) or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T, an attempt to create the type "lvalue reference to cv TR" creates the type "lvalue reference to T" [...]

Your decltype-specifier denotes the type "reference to const int", and you are attempting to create an lvalue reference, so you end up with an lvalue reference to const int.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Would these not apply only to declarations, and not template arguments? I don't see why the rules would change, though. – chris Apr 09 '15 at 14:25
  • So, an rvalue reference type `TR` can be overridden, obtaining an lvalue reference. – Lingxi Apr 09 '15 at 16:05
  • @chris I think the cases of templates are governed by other rules dedicated to them. – Lingxi Apr 09 '15 at 16:08
  • @Lingxi, You can check out [reference collapsing](http://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-a-a-2) for those rules. – chris Apr 09 '15 at 16:17