Search code examples
c++c++14rvalue-referencetype-traits

Store a const reference, whenever an lvalue is passed, and a copy, whenever an rvalue is passed


Please consider the following code:

template<typename T>
class scalar_reference
{
public:
    template<typename U>
    scalar_reference(U&& value)
        : m_value(std::forward<U>(value))
    {}

    T const& operator()() const { return m_value; }

private:
    T m_value;
};

template<typename T>
scalar_reference<T> foo(T&& value) {
    return scalar_reference<T>{ std::forward<T>(value) };
}

The intention is that the scalar_reference returned by foo holds a const reference to a std::decay_t<T> whenever foo is invoked with an lvalue and a copy whenver foo is invoked with an rvalue.

The above code doesn't work. For example, if we call int x; foo(x), T will be int& and hence operator() will return int& too (since the const qualifier has no effect on a reference type).

So, how do we need to change the code?


Solution

  • Is the only problem the return type of operator()? If so, you can just drop the reference first:

    std::decay_t<T> const& operator()() const { return m_value; }