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
Post a Comment