我想转发仿函数调用并仅在绝对必要时复制该仿函数。这是我的通用包装函数和仿函数:
template <typename F>
void wrapper (F func)
{
func ();
}
struct Functor
{
Functor() {}
void operator() () { /* do some work */ }
};
我可以用
调用包装器我想在传递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运算符()
来运行Functorstruct Functor {
Functor() {}
void operator() () const {}
};
在这种情况下,我根本不需要复制包装器的arg。
问题是:如果 Functor 具有const括号运算符,我如何检查包装器?另一个问题是,如果包装器可以更智能和更紧凑的方式实现,而没有大量的类型特征类型typedef? (实际上我不担心代码大小而是关于代码可读性)。
答案 0 :(得分: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>());
}