Have a simple wrapper struct
template<typename T>
struct named_value {
using type = T;
T value{};
string_view name = "unnamed_value";
constexpr explicit operator T&(){ return value; }
constexpr explicit operator T const&()const{ return value; }
constexpr explicit operator T &&()&&{ return std::move(value); }
template<typename U=T>
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }
friend auto operator<<(std::ostream& os, named_value const& a) ->ostream&
{
return os<<a.name<<":"<<a.value;
}
};
Here I try to use universal reference for operator= in order to write less overloads (i.e. for ref, rval ref, const ref). Is this right way?
It's a problematic implementation. The problem is that it may interfere with regular assignment. The compiler generates operator=(name_value const&v) for you, and it takes by a const reference. But when the source object is non-const, the overload generated from the template specialization becomes a better match.
For instance, this code
named_value<int> a;
a = a;
produces this error with GCC
main.cpp: In instantiation of 'constexpr named_value<T>& named_value<T>::operator=(U&&) [with U = named_value<int>&; T = int]':
main.cpp:18:10: required from here
main.cpp:13:51: error: cannot convert 'named_value<int>' to 'int' in assignment
13 | constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }
You need to counter it with SFINAE. So, if we say that things that may go to the compiler generated overload should be rejected. Then ...
template<typename U=T, std::enable_if_t< !std::is_convertible_v<U&&, named_value> , int> = 0>
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }
or, if doing C++20
template<typename U=T> requires (!std::convertible_to<U&&, named_value>)
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }
You may of course opt for other checks, such as std::is_same or std::same_as, depending on the exact semantics you wish to achieve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With