Edit:
This has been reported as a VS2012 C++ compiler bug on Microsoft Connect (link).
Nov. 11, 2014: Microsoft has responded saying the fix for this bug should show up in the next major release of Visual C++.
I've been struggling with a VS2012 compiler error message I don't understand, so I trimmed down the problem to what seems like the bare minimum.
I'm building the following main.cpp
using VS2012:
#include <utility>
template <typename T>
struct A
{
T x;
A(A&& other) : x(std::move(other.x)) { }
A(T&& x) : x(std::move(x)) { }
};
template <typename T>
A<T> build(T&& x)
{
return A<T>(std::move(x));
}
int main(int argc, char* argv[])
{
auto f = []()
{
return build([](){}); //error here
};
return 0;
}
The salient point is that I'm trying to use a lambda as the template type T
of the build
function. The error message I get is:
1> main.cpp
1>C:\test\main.cpp(21): error C2664: 'A<T>::A(A<T> &&)' : cannot convert parameter 1 from 'A<T>' to 'A<T> &&'
1> with
1> [
1> T=void (__cdecl *)(void)
1> ]
1> and
1> [
1> T=main::<lambda_c3c618d445b3cb24eede9bf304860ad7>::()::<lambda_4240e93016e3e420ff8383c9350ae130>
1> ]
1> and
1> [
1> T=void (__cdecl *)(void)
1> ]
1> Reason: cannot convert from 'A<T>' to 'A<T>'
1> with
1> [
1> T=main::<lambda_c3c618d445b3cb24eede9bf304860ad7>::()::<lambda_4240e93016e3e420ff8383c9350ae130>
1> ]
1> and
1> [
1> T=void (__cdecl *)(void)
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
I've done my research and looked up the page for the error message (link), but I still can't figure out what the problem is. Could you please explain this compiler error?
edit
Something is definitely weird here. If I change the code in main
to look like this:
auto f = []()
{
int* n = new int(0);
auto g = [=](){ return *n; };
*n++;
return build<decltype(g)>(std::move(g));
};
I get an error message suggesting that T=int (__cdecl *)(void)
in the call to build - which would mean that decltype(g)
is giving me a function pointer? Huh? I'm capturing a pointer by value and then modifying it afterwards - shouldn't it have to create a functor - and one that has no cast to function pointer? Maybe I'm not understanding something.
See related: Lambda expressions : n3290 draft
Also, if this is a bug in the VS2012 compiler, can you think of a workaround?
I can confirm that using GCC (on linux), this code compiles just fine. So I'd say that VisualStudio seems to be the source of the error.
I don't have Windows or Visual Studio to verify, nor do I have much experience with lambda functions in C++, but perhaps you need to include the (albeit empty) parameter list in the function? i.e. change line 21 to
Both versions compile with GCC, but perhaps Visual Studio is a bit more picky.
The other question I might have is whether the lambda function you're defining at line 24 will work out since its return value involves the lambda function you're defining inside the function itself.