Gabriel
Gabriel

Reputation: 9432

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?

Upvotes: 7

Views: 209

Answers (4)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275405

For the code to do what you want it to do, it would have to read:

  FrontBackBuffer(
    typename std::remove_reference<TBufferTypeFront>::type const&  m_front, 
    typename std::remove_reference<TBufferTypeBack>::type const& m_back):    ////const reference  assigned to reference???
    m_Front(m_front),
    m_Back(m_back)
  {
  };

which has the added "feature" that it turns other types into const references when used to construct FrontBackBuffer.

Now this isn't perfect. This prevents temporary arguments to FrontBackBuffer from being moved, and passes even small cheap to copy types (like char) by reference instead of by value. There are standard C++0x techniques to do this that are a bit awkward to write if you care.

Upvotes: 2

Dave S
Dave S

Reputation: 21113

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.

Upvotes: 5

Oswald
Oswald

Reputation: 31657

FrontBackBuffer::m_Front is of type TBufferTypeFront which translates to int& in your template instantiation. There is nothing wrong with assigning to an int&.

Upvotes: 0

Armen Tsirunyan
Armen Tsirunyan

Reputation: 133014

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&

Upvotes: 13

Related Questions