Unable to instantiate function templates which uses decltype to deduce return type, if called from inside a lambda?
I'm trying to use C++0x, and in particular lambda expression and decltype to simplify some of my code, using the MSVC10 RC compiler.
I've run into the following very odd problem:
template <typename F>
auto foo(F f) -> decltype(f()){
return f();
}
template <typename F>
void bar(F f){
f();
}
int main() {
bar([](){
foo([]() { }); // error C2893: Failed to specialize function template ''unknown-type' foo(F)'
});
}
As indicated in the comment, the compiler generates an error on the line foo([]() { })
.
I hate to shout "compiler bug", but I really can't see any good exp开发者_运维问答lanation for this error.
Apparently, while inside the outer lambda expression, the compiler can not specialize the foo
function template for the inner lambda.
However, if the definition of foo
is changed to hardcode the return type, like this:
template <typename F>
void foo(F f){
return f();
}
then everything compiles just fine.
Is there some obscure quirk of decltype when used to deduce the return type of lambda expression parameters inside the scope of another lambda that I'm not aware of?
These are just some test cases for people to observe.
Works
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
void dummy() {}
int main()
{
auto x = []()
{ // non-lambda parameter
foo(dummy);
};
}
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
int main()
{
auto f = [](){};
auto x = [&]()
{ // pre-defined lambda
foo(f);
};
}
Fails
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
int main()
{
auto x = []()
{ // in-argument lambda
foo([]{});
};
}
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
int main()
{
auto x = []()
{ // in-scope lambda
auto f = []{};
foo(f);
};
}
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
int main()
{
auto x = []()
{ // in-scope lambda, explicit return
// (explicit return type fails too, `-> void`)
auto f = [](){ return; };
foo(f);
};
}
template <typename F>
auto foo(F f) -> decltype(f())
{
return f();
}
int main()
{
auto x = []()
{ // in-argument lambda, explicit return non-void
// (explicit return type fails too, `-> int`)
foo([]{ return 5; });
};
}
So it does seem to have to do with scope and the (?)void
type of the internal lambda, even when made explicit.
The nature of 'auto' is allow compiler to calculate the type. But your first example is contains recursive references on each other, so to calculate auto's of foo you need the bar and to create instance of bar you need the foo.
On other hand second example explicitly tells compiler: "It should be a pointer to function, so calm down for a time". Since pointer to function is well calculated type compiler knows what exactly will be reserved. Just for analogue: compare member's forward declaration
struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
精彩评论