Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template neglects const (why?)

Does somebody know, why this compiles??

template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{

public:


  FrontBackBuffer(
    const TBufferTypeFront  front, 
    const TBufferTypeBack back):    ////const reference  assigned to reference???
     m_Front(front),
     m_Back(back)
  {
  };

  ~FrontBackBuffer()
  {};

  TBufferTypeFront m_Front;       ///< The front buffer
  TBufferTypeBack m_Back;         ///< The back buffer

};

int main(){
    int b;
    int a;
    FrontBackBuffer<int&,int&> buffer(a,b); //
    buffer.m_Back = 33;
    buffer.m_Front = 55;
}

I compile with GCC 4.4. Why does it even let me compile this? Shouldn't there be an error that I cannot assign a const reference to a non-const reference?

like image 208
Gabriel Avatar asked Nov 07 '12 16:11

Gabriel


2 Answers

The thing is that if type T is int&, then the type const T is not const int&, but int & const. The illegal top-level const on a reference is ignored in template substitutions and typedef results.

If, on the other hand T is const int, then T& is const int&

like image 88
Armen Tsirunyan Avatar answered Sep 27 '22 22:09

Armen Tsirunyan


When TypeBufferFront is int&, const TBufferTypeFront is equivalent to int& const, where the const is ignored during template substitution, since all references are constant, even if what they refer to is not.

So, when instantiated with int&, your constructor is effectively FrontBackBuffer(int&, int&), which works as given.

This is an example of why many people will use T const instead of const T, to make it clearer how the substitution occurs, as well as allow them to read the cv-qualifiers from right to left.

like image 23
Dave S Avatar answered Sep 27 '22 23:09

Dave S