有没有办法在C++11中匹配返回值
Any way to match on return value in C++11?
我正试图提供一个调用所提供lambda的函数,我想知道如果该函数的返回类型为void
,是否可以让它返回默认值。
到目前为止,我有一个函数,它返回lambda的返回值,但如果lambda是void
,那么它返回20。
#include <functional>
#include <iostream>
template <typename H>
auto f(H&& h) -> decltype(h(), void())
{
return h();
}
template <typename H>
auto f(H&& h) -> decltype(h(), int())
{
h();
return 20;
}
int main()
{
int r = f([](){ std::cout << "test1" << std::endl; return 10; }); // error here
std::cout << "r: " << r << std::endl;
r = f([](){ std::cout << "test2" << std::endl; });
std::cout << "r: " << r << std::endl;
return 0;
}
这会产生错误,
test.cpp:20:68: error: call of overloaded ‘f(main()::<lambda()>)’ is ambiguous
很明显,这只是由于C++不能使用基于返回类型的多态性。然而,我想知道是否有什么好的C++11技巧,比如更好地使用decltype
或一些模板魔术,可以使这成为可能?我这么问是因为据我所见,这里没有真正的歧义。。编译器推断void
返回类型,然后说是匹配int
版本还是void
版本的f
不明确,这有点傻。
这样做的一个原因是,如果函数f
需要一个返回值,但用户提供的lambda不包括return
语句,则编译器会推断出void
类型,并出错。由于在实际场景中,当用户不愿意提供合理的默认返回值时,我很清楚应该是什么,所以我想知道是否可以让编译器允许用户为了方便而忽略通常不必要的return
语句。
谢谢。我应该提到,我使用的是GCC 4.6.3。
答案:根据Xeo关于使用enable_if
的建议,我提出了以下建议,似乎有效:
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), void>::value, int>::type
{
h();
return 20;
}
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), int>::value, int>::type
{
return h();
}
谢谢!
您可以使用std::enable_if。
第一个返回类型为std::enable_if<!std::is_same<decltype(h()), void>::value, decltype(h())>:type
,第二个返回类型则为std::enable_if<std::is_same<decltype(h()), void>::value, int>::type
。这应该能让你的代码正常工作。我还没有测试过,所以我不确定它是否完全有效。
给我一个理由,说明为什么编译器应该能够根据函数内部的操作来推断为什么要选择哪个重载?在C++中,只有当每个参数都与一个参数匹配时,才考虑重载解析。函数的返回类型和内容无关紧要。
正如STL所说:
TLDR:模板是贪婪的!除非你完全确定会发生什么,否则不要让它们超载。
作为参数的通用引用(template<class T> void f(T&&);
)是你能得到的最贪婪的引用。
你可以像@JKor用SFINAE说的那样解决它,但简化了:
#include <type_traits>
template<class F>
auto f(F f)
-> decltype(true? f() : void())
{
f();
}
template <class F>
auto f(F f) -> decltype(int(f()))
{
f();
return 42;
}
int main(){
f([]{});
}
注意,GCC 4.7有一个错误,decltype(int(void_returning_function()))
不会导致函数SFINAE out。Clang 3.1正确制作
f([]{});
工作,以及
f([]{ return 42; });
- 从python中调用C++函数并获取返回值
- 为什么模板类中的对象不能返回值
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- 返回值优化:显式移动还是隐式
- lock_guard是否保护返回值
- 调用CreateProcess()并获取字符串的返回值
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 查找 GCD:并非所有控制路径都返回值
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 将返回值存储在函数指针数组的指针中是如何工作的?
- C 11返回值和错误对
- 是否可以检索 C++11 中线程函数的返回值
- 当 C++11 应用程序使用非 C++11 库时返回值损坏
- 内存分配,用于在C 11中循环中函数的返回值:如何优化
- 有没有办法在C++11中匹配返回值
- 返回对 C++11 中复数的实数或 IMAG 值的引用的函数
- c++11返回值优化或移动
- C++11-清除返回值语法和decltype关键字
- c++ 11本地命名引用返回值(xvalue)