Seb*_*ner 4 c++ lambda types clang c++11
如果 lambda 的返回类型不匹配,看起来我的 clang 编译器 (3.3) 不会生成任何错误:
#include <functional>
typedef std::function<void()> voidFunc;
void foo(voidFunc func)
{
func();
}
int main()
{
int i = 42;
foo([i]()
{
return i;
});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译此代码不会显示任何错误:
clang++ -c -Xclang -stdlib=libc++ -std=c++11 -Weverything -Wno-c++98-compat -Wno-missing-prototypes -o foo.o foo.cpp
Run Code Online (Sandbox Code Playgroud)
如何针对此类问题生成类型错误?
编辑:
这会产生类型错误:
#include <functional>
struct A {};
struct B {};
typedef std::function<A()> aFunc;
void foo(aFunc func)
{
func();
}
int main()
{
int i = 42;
foo([i]()
{
return B();
});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
foo2.cpp:16:2: error: no matching function for call to 'foo'
foo([i]() {
^~~
foo2.cpp:8:6: note: candidate function not viable: no known conversion from '<lambda at foo2.cpp:16:6>' to 'aFunc' (aka 'function<A ()>') for 1st argument
void foo(aFunc func)
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
std::function是支持特定调用签名的可调用对象的多态容器。
示例中的 lambda 可以像void()调用函数一样进行调用;忽略返回值在 C++ 中从来都不是类型错误(这是一个好主意还是坏主意是另一个问题)。
因此,std::function<void()>允许这样的对象。显示的第一个程序完全有效。
然而,第二个程序中的 lambda 不能在A()函数可以调用的任何地方调用:
void f(A const&);
f(the_lambda()); // nope!
Run Code Online (Sandbox Code Playgroud)
所以第二个程序无效,编译器正确地报告了这一点。
如果您希望在这种情况下出现类型错误,则需要进行自己的类型检查。在这种情况下,您可以简单地static_assert与std::result_of<T()>::type相同void。然而,一般来说,这是不可能的,因为在 C++ 中,由于void()隐式转换等功能,所有可调用对象(除了像 之类的退化可调用对象)都具有多个可能的调用签名。
† 我可能需要在这里解释一下“调用签名”的含义。我的意思是实际调用中使用的类型,或者可能是调用+返回值赋值,而不是声明的签名中明确存在的类型。考虑以下代码。
long f(double);
double d;
int i;
long a = f(d); // call signature is long(double)
// called with double, returning into a long
short b = f(i); // call signature is short(int)
// called with int, returning into a short
Run Code Online (Sandbox Code Playgroud)