具有最少复制的前向函子

Forward functors with minimal copying

本文关键字:复制      更新时间:2023-10-16

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

template <typename F>
void wrapper (F func)
{
  func ();
}
struct Functor
{
  Functor() {}
  void operator() () { /* do some work */ }
};

我可以用调用包装器

  1. 右值引用:包装器(Functor())
  2. 左值引用:函数f;包装物(f)
  3. const左值引用:const函数f;包装物(f)
  4. const右值引用:const函数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运算符的Functor()

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

在这种情况下,我根本不需要复制包装器的参数。

问题是:如果Functor有const圆括号运算符,我如何签入包装?另一个问题是,包装器是否可以以更智能、更紧凑的方式实现,而不需要大量的类型特征行typedefs?(实际上,我担心的不是代码大小,而是代码的可读性)。

如果您只是想在对引用的调用有效的情况下使用引用,请使用表达式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>());
}