尝试使用具有尾随返回类型的 lambda 进行 SFINAE 时出现硬错误
Hard error when attempting SFINAE with lambda that has trailing return type
我在SO上看到了解释为什么SFINAE不适用于lambda返回类型的答案。我稍微改变了我的设计,但现在收到了一个更奇怪的错误。我不知道我错过了什么。代码将使用 C++11、14 和 17 进行编译。我有一个兼容C++17的apply
.
#include <algorithm>
#include <vector>
#include <functional>
#include <tuple>
#include <utility>
template <typename ...T>
struct S {
std::vector<std::tuple<T...>> things;
template <typename F>
typename std::enable_if<std::is_same<
typename std::invoke_result<
std::apply<F, T...>, F, T...>::type, bool>::value,
bool>::type
find_if(const F &f) {
return std::any_of(things.begin(), things.end(),
[&](const std::tuple<T...> &t) {
return std::apply(f, t);
});
}
template <typename F>
auto find_if(const F &f) -> decltype(std::declval<F>()(things.front())) {
return std::any_of(things.begin(), things.end(),
[&](const std::tuple<T...> &t) { return f(t); });
}
};
void f() {
S<int, float> s;
auto l = [](const std::tuple<int, float> &) -> bool { return false; };
s.find_if(l);
}
我的目的是调用正确的谓词。如果谓词具有std::tuple<Ts...>
类型的单个参数,则直接调用它。如果谓词参数列表与解压缩的模板参数包匹配,请调用该参数包。
GCC和Clang都抱怨第一种方法,其中apply
不是一种类型。
<source>:13:26: error: type/value mismatch at argument 1 in template parameter list for 'template<class _Functor, class ... _ArgTypes> struct std::invoke_result'
13 | std::apply, F, T...>::type, bool>::value,
| ^
<source>:13:26: note: expected a type, got 'std::apply'
元函数std::invoke_result
期望它的第一个参数是可调用的东西的类型,以及参数的类型。
不幸的是,std::apply
不是一种类型,而是一个函数。此外,std::apply
使用类型推导,因此它对 sfinae 不友好。
解决方案是使用可调用对象的类型,而不是要应用的调用。
template <typename ...T>
struct S {
std::vector<std::tuple<T...>> things;
template <typename F, typename std::enable_if_t<
std::is_same_v<std::invoke_result_t<F, T...>, bool>, int> = 0>
auto find_if(const F &f) -> bool {
return std::any_of(things.begin(), things.end(),
[&](const std::tuple<T...> &t) {
return std::apply(f, t);
});
}
};
此外,您的 lambda 应如下所示:
[](int, float) -> bool { return false; };
这是因为 apply 正在分解元组。
相关文章:
- 通过递归进行因子分解
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 为什么使用SFINAE而不是函数重载
- 使用libgit2、c++进行pull
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何使用模板函数的函数签名进行SFINAE
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 进行 SFINAE 练习时编译错误
- C++ SFINAE:如果可能,对 STD 集合进行排序
- 在 C++ 中使用 SFINAE 进行模板推导
- 尝试使用具有尾随返回类型的 lambda 进行 SFINAE 时出现硬错误
- 如何对 SFINAE 进行"deep",即当替换导致代码中进一步出现一些编译错误时?
- 使用函数模板和 SFINAE 通过参数进行区分
- 表达式 SFINAE 对传递的函数指针的类型进行重载
- 在 C++11 中使用 SFINAE 在具有相同签名的两个函数之间进行选择
- 使用 SFINAE 进行结构定义
- 如何使用SFINAE为枚举类中缺少的值进行polyfill