eile
eile

Reputation: 1153

template function and boost::remove_reference

I'm tracking down a C++ compiler error which I can't figure out. I've reduced it to this code:

#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>

template<typename T> inline const T bar( T in )
{
    typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type nonref;
    const nonref* inPtr = &in;
    return *inPtr;
}

class Foo
{
};

int main()
{
    Foo foo;
    const Foo& ref = bar< Foo& >( foo );
}

which results in:

tt.cpp: In function ‘const T bar(T) [with T = Foo&]’:
tt.cpp:19:39:   instantiated from here
tt.cpp:9:13: error: invalid initialization of reference of type ‘Foo&’ from expression of type ‘const nonref {aka const Foo}’

What's the actual issue here? Why is the const missing in the return value? I need the remove_reference since the actual code requires it.

Upvotes: 1

Views: 746

Answers (3)

FireAphis
FireAphis

Reputation: 6790

Returning const T from your function doesn't do what you are expecting. From your code I understand that you expect it to return const Foo&, which is a reference to an immutable object of type Foo.

But when T is Foo&, the expression const T means an immutable reference to an object of type Foo. Since the references are always immutable, the const part is just dropped (according to the paragraph 8.3.2 of the spec)! That is, your function returns Foo& and not const Foo& and that's what the compiler tries to tell you.

Upvotes: 0

Stephen Nutt
Stephen Nutt

Reputation: 3306

Using VisualStudio 2008 I get the following error

error C2440: 'return' : cannot convert from 'const nonref' to 'Foo &'

Changing bat to

template<typename T> inline const typename boost::remove_reference<T>::type& bar( T in )
{
    typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type nonref;
    const nonref* inPtr = &in;
    return *inPtr;
}

fixes this and the code compiles.

Upvotes: 1

Potatoswatter
Potatoswatter

Reputation: 137830

Applying const to a reference type does nothing. You need to make the template argument const foo &, or else remove the reference and then add back both const and the reference in the function signature itself.

See also When should I use remove_reference and add_reference? particularly the second paragraph.

Upvotes: 3

Related Questions