4

編集:

これは、Microsoft Connect (リンク)で VS2012 C++ コンパイラのバグとして報告されています。

2014 年 11 月 11 日: Microsoft は、このバグの修正が Visual C++ の次のメジャー リリースで表示されるはずであると回答しました。


私は理解できないVS2012コンパイラエラーメッセージに苦労していたので、問題を最小限に抑えました。

私はmain.cppVS2012を使用して以下を構築しています:

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

顕著な点は、ラムダを関数のテンプレート型として使用しようとしていること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

調査を行い、エラー メッセージ (リンク)のページを調べましたが、まだ問題の原因がわかりません。このコンパイラエラーについて説明していただけますか?


編集

ここで何かが明らかにおかしい。コードを次のmainように変更すると:

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

T=int (__cdecl *)(void)build の呼び出しでそれを示唆するエラー メッセージが表示されます。これはdecltype(g)、関数ポインタが与えられていることを意味しますか? は?私はポインタを値でキャプチャし、後でそれを変更しています - ファンクタを作成する必要はありません - そして関数ポインタへのキャストを持たないものですか? たぶん私は何かを理解していません。

関連参照:ラムダ式 : n3290 ドラフト


また、これVS2012 コンパイラのバグである場合、回避策を考えてもらえますか?

4

3 に答える 3

2

確認する Windows や Visual Studio はありません。また、C++ でラムダ関数を使用した経験もあまりありませんが、関数に (空ではありますが) パラメーター リストを含める必要があるのではないでしょうか? つまり、21行目を次のように変更します

return build([](){});

どちらのバージョンも GCC でコンパイルされますが、おそらく Visual Studio はもう少しうるさいです。

もう 1 つの質問は、24 行目で定義しているラムダ関数が機能するかどうかということです。その戻り値には、関数自体の内部で定義しているラムダ関数が含まれているからです。

于 2013-05-21T04:23:17.020 に答える