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?
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; }