【发布时间】:2017-02-17 09:36:44
【问题描述】:
我可以写一个特征元函数来判断一个类型是否是函子吗?
例如,有大量代码可以使用decltype(&T::operator()) 的 SFINAE 来检查函子,
template<class T>
struct is_functor {
template<class F>
static auto test(decltype(&F::operator())) -> std::true_type;
template<class F>
static auto test(...) -> std::false_type;
static constexpr bool value = decltype(test<T>(0))::value;
};
但是,这不适用于泛型 lambda,因为泛型 lambda
的operator() 是一个模板函数。
有一些用于泛型 lambda 版本的有限情况的代码,它们对泛型 lambda 的参数类型进行了一些限制。例如,如果 lambda 表达式包含任何对 int 类型无效的表达式(例如成员访问操作),则此处的答案 (https://stackoverflow.com/a/5117641/2580815) 将不起作用。
我不需要任何通用性。事实上,我只需要知道一个类型可以是一个只接受一个参数的函子。
如何实现我的is_functor?
用例:
我正在尝试验证给定参数是否是模板函数的仿函数,也就是说,我想要一些重载的模板函数,例如:
template<class F, class = enable_if_t<is_functor<std::decay_t<F>>::value>>
auto make_func(F &&f) { return std::forward<F>(f); }
template<class F, class = enable_if_t<!is_functor<std::decay_t<F>>::value>>
auto make_func(F &&f) { return [f=std::forward<F>(f)] (auto&&) { return f; }; }
【问题讨论】:
-
如果您的编译器足够新以支持某些 C++17 功能,您或许可以使用
std::is_callable。 -
@Someprogrammerdude 它只适用于已知的参数类型。
-
@Someprogrammerdude 不,
std::is_callable完全不同。它需要同时使用仿函数类型F和参数类型Args...来解决模棱两可的重载函数。我不在乎论点的模棱两可。我只关心 operator() 的存在。 -
为什么您需要知道
operator()是否存在并且可以接受一些未知类型的参数? -
@n.m.我添加了一个用例示例。
标签: c++ lambda functor generic-lambda