3

I have a class template that accepts a type T. It has a method. I want this method to return type T if it is const and T& if it is non-const.

template<typename T>
class C
{
    static typename add_reference_if_non_const<T>::type method();
};

int main()
{
    assert( is_same<result_of<C<int>::method()>::type, int&>::value );
    assert( is_same<result_of<C<const int>::method()>::type, const int>::value );
}

How can I do it?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
haael
  • 972
  • 2
  • 10
  • 22

2 Answers2

2

You want the return type of C<int const>::method() to be int const, but top-level cv qualifiers are ignored on function return types. In any case, since method() returns a copy of T, do you really care that you return T const and not T?

Given that, I think what you want is the following

using add_reference_if_non_const =
    typename std::conditional<std::is_const<T>{},
                              typename std::remove_const<T>::type,
                              typename std::add_lvalue_reference<T>::type
                >::type;
static add_reference_if_non_const method();

You can replace typename std::remove_const<T>::type with T if you want to return T const when T is a class type.


The next problem is with result_of which works with type arguments; what you have in the question is a function call of C::method. You need to use

result_of<decltype(&C<int>::method)()>::type

But since you need to use decltype anyway, you can completely do away with result_of.

decltype(C<int>::method())

Finally, you don't need to assert at runtime when you can make the checks at compile time using static_assert

static_assert( is_same<decltype(C<int>::method()),       int&>::value, "");
static_assert( is_same<decltype(C<int const>::method()), int>::value,  "" );

Live demo

Praetorian
  • 106,671
  • 19
  • 240
  • 328
1

How about this:

template <typename T>
struct add_reference_if_non_const
{
    using type = std::conditional<std::is_const<T>::value, T, std::add_lvalue_reference<T>>::type;
};
m.s.
  • 16,063
  • 7
  • 53
  • 88