lambda 转换为 bool 而不是推导函数指针类型
lambda converted to bool instead of deducing function-pointer-type
我想为 operator<<
实现一个重载,它允许我调用给定的函数并输出结果。
因此我写了一个重载,但是选择了转换为 bool 并且当我自己写一个函数时,它不会编译。
编辑:知道我不想调用 lambda,
而是将它传递给应该使用默认构造的参数列表调用它的函数。
我已经附加了我的代码:
#include <iostream>
template<typename T>
void test(T *) {
std::cout << "ptr" << std::endl;
}
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
template<typename Ret, typename ...Args>
void test(Ret(*el)(Args...)) {
std::cout << "function ptr\n" << el(Args()...) << std::endl;
}
template<typename Char_T, typename Char_Traits, typename Ret, typename ...Args>
std::basic_ostream<Char_T, Char_Traits>& operator<<(
std::basic_ostream<Char_T, Char_Traits> &str, Ret(*el)(Args...)) {
return str << el(Args()...);
}
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test([]{return 5;}); // will not compile
}
我使用带有版本标记 -std=c++14
的 gcc 7.3.1。
编辑:错误信息:
main.cc: In function ‘int main()’:
main.cc:25:23: error: no matching function for call to ‘test(main()::<lambda()>)’
test([]{return 5;});
^
main.cc:5:6: note: candidate: template<class T> void test(T*)
void test(T *) {
^~~~
main.cc:5:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘T*’ and ‘main()::<lambda()>’
test([]{return 5;});
^
main.cc:9:6: note: candidate: template<class T> void test(bool)
void test(bool) {
^~~~
main.cc:9:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: couldn't deduce template parameter ‘T’
test([]{return 5;});
^
main.cc:13:6: note: candidate: template<class Ret, class ... Args> void test(Ret (*)(Args ...))
void test(Ret(*el)(Args...)) {
^~~~
main.cc:13:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘Ret (*)(Args ...)’ and ‘main()::<lambda()>’
test([]{return 5;});
您的问题是模板参数推导 仅 在传递给 test
的实际参数上完成。并不是对参数可能转换成的所有可能类型都这样做。那可能是一个无限集,所以这显然是 no-go.
因此,模板参数推导是在实际的 lambda 对象上完成的,它具有无法描述的 class 类型。因此 test(T*)
的推导失败,因为 lambda 对象不是指针。 T
显然不能从 test(bool)
推导出来。最后,test(Ret(*el)(Args...))
的推导失败,因为 lambda 对象也不是 pointer-to-function。
有几个选项。您甚至可能不需要模板,您可以接受 std::function<void(void)>
并依赖于它具有模板化构造函数这一事实。或者你可以只接受一个 test(T t)
参数并将其称为 t()
。 T
现在将推断为实际的 lambda 类型。最奇特的解决方案可能是使用 ,并接受模板可变参数列表。
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
不需要模板。事实上,你重载了函数,而不是模板。替换为
void test(bool) {
std::cout << "bool" << std::endl;
}
现在您的示例将编译。
即使 non-capturing lambdas 有一个到函数指针的隐式转换,函数模板必须完全匹配才能成功推导,不会执行任何转换。
因此,最简单的解决方法是使用 +
强制转换
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test(+[]{return 5;});
// ^
}
我想为 operator<<
实现一个重载,它允许我调用给定的函数并输出结果。
因此我写了一个重载,但是选择了转换为 bool 并且当我自己写一个函数时,它不会编译。
编辑:知道我不想调用 lambda, 而是将它传递给应该使用默认构造的参数列表调用它的函数。
我已经附加了我的代码:
#include <iostream>
template<typename T>
void test(T *) {
std::cout << "ptr" << std::endl;
}
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
template<typename Ret, typename ...Args>
void test(Ret(*el)(Args...)) {
std::cout << "function ptr\n" << el(Args()...) << std::endl;
}
template<typename Char_T, typename Char_Traits, typename Ret, typename ...Args>
std::basic_ostream<Char_T, Char_Traits>& operator<<(
std::basic_ostream<Char_T, Char_Traits> &str, Ret(*el)(Args...)) {
return str << el(Args()...);
}
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test([]{return 5;}); // will not compile
}
我使用带有版本标记 -std=c++14
的 gcc 7.3.1。
编辑:错误信息:
main.cc: In function ‘int main()’:
main.cc:25:23: error: no matching function for call to ‘test(main()::<lambda()>)’
test([]{return 5;});
^
main.cc:5:6: note: candidate: template<class T> void test(T*)
void test(T *) {
^~~~
main.cc:5:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘T*’ and ‘main()::<lambda()>’
test([]{return 5;});
^
main.cc:9:6: note: candidate: template<class T> void test(bool)
void test(bool) {
^~~~
main.cc:9:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: couldn't deduce template parameter ‘T’
test([]{return 5;});
^
main.cc:13:6: note: candidate: template<class Ret, class ... Args> void test(Ret (*)(Args ...))
void test(Ret(*el)(Args...)) {
^~~~
main.cc:13:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘Ret (*)(Args ...)’ and ‘main()::<lambda()>’
test([]{return 5;});
您的问题是模板参数推导 仅 在传递给 test
的实际参数上完成。并不是对参数可能转换成的所有可能类型都这样做。那可能是一个无限集,所以这显然是 no-go.
因此,模板参数推导是在实际的 lambda 对象上完成的,它具有无法描述的 class 类型。因此 test(T*)
的推导失败,因为 lambda 对象不是指针。 T
显然不能从 test(bool)
推导出来。最后,test(Ret(*el)(Args...))
的推导失败,因为 lambda 对象也不是 pointer-to-function。
有几个选项。您甚至可能不需要模板,您可以接受 std::function<void(void)>
并依赖于它具有模板化构造函数这一事实。或者你可以只接受一个 test(T t)
参数并将其称为 t()
。 T
现在将推断为实际的 lambda 类型。最奇特的解决方案可能是使用
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
不需要模板。事实上,你重载了函数,而不是模板。替换为
void test(bool) {
std::cout << "bool" << std::endl;
}
现在您的示例将编译。
即使 non-capturing lambdas 有一个到函数指针的隐式转换,函数模板必须完全匹配才能成功推导,不会执行任何转换。
因此,最简单的解决方法是使用 +
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test(+[]{return 5;});
// ^
}