I have design a little class to allow to overload a function with universal references for a known type, but I'm not sure if that class will work as expected in any contexts.The indended purpose is to allow overload a ''universal reference'' templated function, for specific types:template<class arg_t>void fun(arg_t&& obj); // obj will be just forwarded// Overload for std::string but unaware of qualifiers, for// forwarding purposes.template<class arg_t = std::string?>void fun(arg_t&& str);C++ currently doesn't offer any feature to allow that (templated qualifiers). So, my class is like a std::reference_wrapper, but transporting in a second template parameter the decayed type, to write things like:// Overloads the generic version for a std::string qualified family.template<class qualified_t>void fun(uref<qualified_t, std::string> uref){ fun2(uref.get()); } // No need to do std::forwardThe get() return type will be std::string&, std::string const& or std::string&&.That is the best I was able to achieve:template<class ref_type_t, class type_t = std::decay_t<ref_type_t> >class uref{    ref_type_t o;public:    using type = type_t;    using ref_type = ref_type_t;    static_assert(std::is_reference<ref_type>::value,                  ref_type must be a reference);    explicit uref(ref_type t) : o(std::forward<ref_type>(t)) {}    ref_type get() { return std::forward<ref_type>(o); }    type const& get() const { return o; }    template<class T, class =         std::enable_if_t<std::is_convertible_v<ref_type, T>                    and !std::is_same_v<std::decay_t<T>, type>> >    operator T() const { return get(); }    template<class T, class =         std::enable_if_t<std::is_convertible_v<type const&, T>                    and !std::is_same_v<std::decay_t<T>, type>> >    operator T() { return get(); }    operator type const&() const & { return o; }    operator type&() & { return o; }    operator ref_type() && { return std::forward<ref_type>(o); }};template<class type>uref<type&&> make_uref(type&& t){ return uref<type&&>(std::forward<type>(t)); }The way of using it is:void client(float) { std::cout << Floating << std::endl; }void client(std::string const&){ std::cout << From const char* to std::string << std::endl; }template<class param_t>auto service(param_t&& arg){ return client(make_uref(std::forward<param_t>(arg))); }template<class ref_t>void client(uref<ref_t, std::string>){ std::cout << Specific << std::endl; }int main(){    service(3);    service(std::string(Hi!));    service(Hi!);    service(3.f);    return 0;}Since uref saves the original reference type on the first template parameter T, and with get() you get the reference as-is, and you can have different universal reference overloads for different ''decayed'' types. With the conversion operators, the client can receive the type without begin wrapped, the conversion will free the reference bound on the service parameter. You can still use the reference wrapper to construct other objects to any convertible-to type.The question is, is desirable to have such an object? Can be seen as an anti-pattern? For example, the two overloads, receiving a std::string and uref<T, std::string>, can confused the reader, specifically, when each one of them will be called.Any downside of this design?
Reference wrapper for functions overloadings and universal references
c++;template;wrapper;overloading;reference