扩展std :: function以消除重载函数的歧义

时间:2016-01-24 16:18:24

标签: c++ c++14 overloading std-function

当前std::function不消除重载函数的歧义(参见最后的示例)。因此,当从重载函数构造或分配时,用户必须手动消除歧义(例如,使用显式强制转换),这很烦人。由于std::function具有函数签名信息,因此它实际上可以自动消除歧义。所以,我尝试从function中创建一个新的std::function,最后得到以下代码。扩展标准库可能非常棘手且容易出错。所以,我想知道我是否遗漏了某些东西,或者存在更好的解决方案。具体来说,我可以为我的新std::uses_allocator部分专门化function吗? (可以找到代码的原始版本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 {};

}

一个例子:

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
}

0 个答案:

没有答案