我正在使用如下定义的is_callable
结构
template <typename F, typename... Args>
struct is_callable {
template <typename U>
static auto test(U* p) -> decltype((*p)(std::declval<Args>()...), void(), std::true_type());
template <typename U>
static auto test(...) -> decltype(std::false_type());
static constexpr bool value = decltype(test<F>(nullptr))::value;
};
我用它来测试声明为:
的lambdatemplate <typename T>
struct runner {
T t;
template <typename F, typename = typename std::enable_if<is_callable<F, T&>::value || is_callable<F, T&&>::value>::type>
void run(F&& f) {
return f(t);
}
};
runner<int> a{0};
a.run([&] (auto& x) {
x++;
});
为什么在AppleClang上的enable_if
上编译失败? auto
不应该被正确推断出来吗?
答案 0 :(得分:1)
true_type
test
的案例看起来不对。无论如何,您的代码比它需要的更复杂。尝试以下最小的工作示例:
#include <utility>
template<typename F, typename...Args> struct is_callable {
template<typename F2, typename...Args2> static constexpr std::true_type
test(decltype(std::declval<F2>()(std::declval<Args2>()...)) *) { return {}; }
template<typename F2, typename...Args2> static constexpr std::false_type
test(...) { return {}; }
static constexpr bool value = decltype(test<F, Args...>(nullptr))::value;
};
void f0();
static_assert(is_callable<decltype(f0)>::value, "f0()");
static_assert(!is_callable<decltype(f0), int>::value, "f0(0)");
int f1(int);
static_assert(!is_callable<decltype(f1)>::value, "f1()");
static_assert(is_callable<decltype(f1), int>::value, "f1(0)");
static_assert(!is_callable<decltype(f1), int, int>::value, "f1(0, 0)");
auto __attribute__((unused)) f2 = [](int, char *) { return 7; };
static_assert(is_callable<decltype(f2), int, char *>::value, "f2(int, char *)");
static_assert(!is_callable<decltype(f2), int, int>::value, "f2(int, int)");
答案 1 :(得分:0)
问题不在于is_callable
测试类,而是您对它的使用。
在功能的模板参数列表中使用std::enable_if
时,您必须以这种方式使用它:
template <typename T>
struct runner {
T t;
template
<
typename F,
std::enable_if_t<is_callable<std::decay_t<F>, T&>::value || is_callable<F, T&&>::value>* = nullptr
>
void run(F&& f) {
return f(t);
}
};
您尝试使用的表单用作尾随返回类型:
template<typename F>
auto run(F&& f)
-> std::enable_if_t<is_callable<std::decay_t<F>, T&>::value || is_callable<F, T&&>::value>
{
return f(t);
}
is_callable
类型是正确的。它看起来像我之前发布的堆栈溢出。