c++ - Extend std::function to disambiguate overloaded function -


current std::function not disambiguate overloaded function (see example @ end). consequently, when constructing or assigning overloaded function, users have disambiguate manually (with explicit cast example), annoying. since std::function has function signature information, can disambiguate automatically. so, tried make such new function out of std::function, , ended following code. extending standard library can tricky , error-prone. so, i'm wondering whether i'm missing something, or better solution exists. specifically, it ok me partial-specialize std::uses_allocator new function? (original version of code can found here)

template <typename r, typename... args> class function<r(args...)> : public std::function<r(args...)> { private:   template <typename f_, typename f = std::decay_t<f_>>   using enable_if_fn_t = std::enable_if_t<                            std::is_same<r, std::result_of_t<f(args...)>>                            ::value>;  public:   using base = std::function<r(args...)>;    function(r(*ptr)(args...)) : base{ptr} {}   function() = default;   function(std::nullptr_t) : base{nullptr} {}   template <typename f, typename = enable_if_fn_t<f>>   function(f f) : base{std::move(f)} {}   template <typename alloc>   function(std::allocator_arg_t tag, const alloc& alloc)       : base{tag, alloc} {}   template <typename alloc>   function(std::allocator_arg_t tag, const alloc& alloc, std::nullptr_t)       : base{tag, alloc, nullptr} {}   template <typename f, typename alloc, typename = enable_if_fn_t<f>>   function(std::allocator_arg_t tag, const alloc& alloc, f f)       : base{tag, alloc, std::move(f)} {}   template <typename alloc>   function(std::allocator_arg_t tag, const alloc& alloc, const function& other)       : base{tag, alloc, static_cast<const base&>(other)} {}   template <typename alloc>   function(std::allocator_arg_t tag, const alloc& alloc, function&& other)       : base{tag, alloc, std::move(static_cast<base&>(other))} {}    function& operator =(r(*ptr)(args...)) {     base::operator =(ptr);     return *this;   }   function& operator =(std::nullptr_t) {     base::operator =(nullptr);     return *this;   }   template <typename f, typename = enable_if_fn_t<f>>   function& operator =(f&& f) {     base::operator =(std::forward<f>(f));     return *this;   }   template <typename f, typename = enable_if_fn_t<f>>   function& operator =(std::reference_wrapper<f> f) {     base::operator =(f);     return *this;   } };  namespace std {  template <typename r, typename... args, typename alloc> struct uses_allocator<::function<r(args...)>, alloc> : true_type {};  } 

an example:

void func(int) {} void func(char) {}  int main() {   // std::function<void(int)> f = func; // construction not ok   // f = func; // assignment not ok   function<void(int)> f = func; // construction ok   f = func; // assignment ok } 


Comments