5

一般的なラムダ関数が与えられたときに非自動パラメーターの型を取得するコードをいくつか書きました。以下のコードでわかるように、一般的なラムダを使用して connect 関数を呼び出し、auto パラメーターに引数を提供するという考え方です (私のユース ケースでは常に先頭に配置されます)。したがって、以下のコードでの私の目標は、2 番目のパラメーターが float 型であることを検出することでした。

コードは clang 3.8 では正常に動作しますが、gcc 6.1.1 ではコンパイルされません。これは gcc のバグなのか、それとも有効な C++ コードではないのか疑問に思っていました。汎用ラムダがテンプレート化された operator() 関数で実装されていると仮定できますか、それともこれはコンパイラ固有のものですか?

template <typename Functor, typename... AllArgs, typename... ProvidedArgs>
void findArgTypes(void(Functor::*)(AllArgs...) const, Functor, ProvidedArgs...)
{
    // AllArgs == int, float
    // ProvidedArgs == int
}

template <typename Func, typename... ProvidedArgs>
void connect(Func func, ProvidedArgs... providedArgs)
{
    findArgTypes(&Func::template operator()<ProvidedArgs...>, func, providedArgs...);
}

int main()
{
    int tmp = 0;
    connect([&](auto, float){ ++tmp; }, 0);
}

gcc が与えるエラーは次のとおりです。

main.cpp: In instantiation of ‘void connect(Func, ProvidedArgs ...) [with Func = main()::<lambda(auto:1, float)>; ProvidedArgs = {int}]’:
main.cpp:16:33:   required from here
main.cpp:11:17: error: no matches converting function ‘operator()’ to type ‘void (struct main()::<lambda(auto:1, float)>::*)() const’
     findArgTypes(&Func::template operator()<ProvidedArgs...>, func, providedArgs...);
     ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:27: note: candidate is: template<class auto:1> main()::<lambda(auto:1, float)>
     connect([](auto, float){}, 0);
                           ^

constfindArgTypesの を削除すると、同じ結果が得られます。

次のコードを使用すると、両方のコンパイラで機能します。

struct Foo
{
    template <typename T>
    void operator()(T, float) const {}
};

int main()
{
    Foo f;
    connect(f, 0);
}
4

1 に答える 1

1

ファンクター(オブジェクト)を期待しているため、エラーが発生しましたが、空のキャプチャを持つラムダはフリー関数に変換可能です:

int main() {
    using function = void (*)(int, float);
    function a = [](auto, float){};
}

cppreference のラムダを参照してください:


実装が両方のコンパイラを満たしているという質問の最新バージョンの場合:

template <typename Func, typename... ProvidedArgs>
void connect(Func func, ProvidedArgs... providedArgs)
{
    auto mf = &Func::template operator()<ProvidedArgs...>;
    findArgTypes(mf, func, providedArgs...);
}

autoこれは、gcc が正しく機能するためにこのローカル変数が必要な gcc コンパイラのバグだと思います...

ところで、1 つの質問 - clang の 1 つのバグ、gcc の 1 つ - 目標を達成するためのより簡単な方法を見つけることを本当にお勧めします - おそらくstd::function、まったく新しい汎用ラムダの代わりに使用することを検討してください。

于 2016-06-22T15:38:14.970 に答える