Reputation: 9432
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
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
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
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
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