使用lambda作为模板参数时,这个编译器错误是什么?

问题描述 投票:4回答:3

Edit:

这已被报告为Microsoft Connect (link)上的VS2012 C ++编译器错误。

2014年11月11日:微软已经回应说这个bug的修复程序应该出现在Visual C ++的下一个主要版本中。


我一直在努力解决我不明白的VS2012编译器错误消息,所以我把问题减少到了最低限度。

我正在使用VS2012构建以下main.cpp

#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;
}

重点是我正在尝试使用lambda作为T函数的模板类型build。我得到的错误信息是:

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

我已经完成了我的研究并查找了错误消息页面(link),但我仍然无法弄清楚问题是什么。你能解释一下这个编译错误吗?


edit

这里肯定有些奇怪。如果我将main中的代码更改为如下所示:

auto f = []()
{
    int* n = new int(0);
    auto g = [=](){ return *n; };
    *n++;
    return build<decltype(g)>(std::move(g));
};

我收到一条错误消息,建议在构建调用中使用T=int (__cdecl *)(void) - 这意味着decltype(g)正在给我一个函数指针?咦?我正在按值捕获一个指针然后再修改它 - 它不应该创建一个仿函数 - 并且没有强制转换为函数指针吗?也许我不理解某些事情。

见相关:Lambda expressions : n3290 draft


另外,如果这是VS2012编译器中的错误,您能想到一个解决方法吗?

c++ templates visual-studio-2012 c++11 lambda
3个回答
3
投票

我可以确认使用GCC(在linux上),这段代码编译得很好。所以我会说VisualStudio似乎是错误的来源。


2
投票

我没有Windows或Visual Studio来验证,也没有在C ++中使用lambda函数的经验,但是你可能需要在函数中包含(虽然是空的)参数列表?即将第21行改为

return build([](){});

两个版本都使用GCC进行编译,但也许Visual Studio有点挑剔。

我可能遇到的另一个问题是你在第24行定义的lambda函数是否会解决,因为它的返回值涉及你在函数本身内定义的lambda函数。


0
投票

我不知道这种行为是否符合标准,但VC ++ 2019只有选项/ permissive-才会发生错误,然后当严格模式打开时。

然而,这里是如何解决问题,只需使用引用类型转换lambda:

template <typename FUNC>
void f(FUNC& o){}

int main()
{
    f((std::function<void()>&)[](){});
    // or also:
    auto func = [](){};
    f(func);
}
© www.soinside.com 2019 - 2024. All rights reserved.