4

我想转发仿函数调用并仅在绝对必要时复制该仿函数。这是我的通用包装函数和仿函数:

template <typename F>
void wrapper (F func)
{
  func ();
}

struct Functor
{
  Functor() {}
  void operator() () { /* do some work */ }
};

我可以用

  1. 右值引用:包装器(Functor());
  2. 左值参考:函子 f;包装器(f);
  3. const 左值参考:const Functor f; 包装器(f);
  4. const 右值参考:const Functor make_functor(); 包装器(make_functor());

我只想在传递 const 引用时复制包装器的 arg。所以我来了这样的包装器实现:

using safe_mutual_handler_type =
  typename std::conditional<
    std::is_reference<F>::value
  , typename std::conditional<
      std::is_const<typename std::remove_reference<F>::type>::value
    , typename std::remove_const<typename std::remove_reference<F>::type>::type
    , F&
    >::type
  , F&
  >::type;

template <typename F>
void wrapper (F&& func)
{
  safe_mutual_handler_type<F> tmp = func;
  tmp ();
}

不是很好并且错过了(不是很典型)const-rvalue-reference 案例,但基本上可以完成它的工作。

但我也可能有带有 const operator() 的 Functor

struct Functor {
  Functor() {}
  void operator() () const {}
};

在那种情况下,我根本不需要复制包装器的 arg。

问题是:如果Functor有 const 括号运算符,我如何检查包装器?另一个问题是包装器是否可以在没有大量类型特征 typedef 行的情况下以更智能和更紧凑的方式实现?(实际上我担心的不是代码大小,而是代码的可读性)。

4

1 回答 1

5

如果您只想在调用有效的情况下使用引用,请使用表达式 SFINAE:

template <typename F>
auto wrapper_ (F&& func, int) -> decltype(func())
{
    func ();
}

template <typename F>
void wrapper_ (F func, ...)
{
    func ();
}

template <typename F>
void wrapper (F&& f)
{
    wrapper_(std::forward<F>(f), 0);
}

如果您只想在传递可变引用时复制/移动它(并且仅在那时):

template <typename F>
auto wrapper_ (F&& func, std::true_type)
{
    func ();
}

template <typename F>
void wrapper_ (F func, std::false_type.)
{
    func ();
}

template <typename F>
void wrapper (F&& f)
{
    wrapper_(std::forward<F>(f), std::is_const<typename std::remove_reference<F>::type>());
}
于 2014-10-13T18:04:15.460 回答