c++templatesc++11language-lawyertemplate-aliases

What's the formal of C++ const reference (not reference to const, but const reference)


Given

template< class Type >
void constref( Type const ) {}

void constref_call() { double x; constref<double&>( x ); }      // OK

template< class Type >
using reference = Type&;

void foo( reference< const int > const x ) { (void) x; }        // OK

template< class Type >
void foot( reference< const Type > arg ) { (void) arg; }

void foot_call() { foot( 3.14 ); }      // Deduces arg type no problem.

void foo2( int const& const x ) { (void) x; }                   // !

With both Visual C++ and g++ this code compiles as indicated in the comments, with only foo2 provoking a compilation error.

I would have liked foo to similarly result in compilation error, in order to be able to use that notation with the same constraints as the core language's “failed experiment” operator notation.

I suspect that the reason that foo compiles is the same as the reason why the call in constref_call compiles, some exemption to do with templates, but is that really so – what are the standard's formal rules here?


Solution

  • Quoting C++11, 8.3.2/1:

    ... Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef (7.1.3) or of a template type argument (14.3), in which case the cv-qualifiers are ignored. ...