从泛型lambda检测参数类型 - 使用GCC编译错误

时间:2016-06-22 14:45:12

标签: c++ gcc lambda c++14 generic-lambda

我写了一些代码,在给定通用lambda函数时检索非auto参数的类型。正如您在下面的代码中看到的那样,我们的想法是使用通用lambda调用connect函数,并为auto参数提供参数(在我的用例中总是位于前面)。所以在下面的代码中,我的目标是检测第二个参数是float类型。

代码与clang 3.8一起工作正常,但它不能用gcc 6.1.1编译,所以我想知道这是否是gcc中的错误或者这是不是有效的c ++代码?我可以假设一个泛型lambda是用模板化的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);
                           ^

删除findArgTypes中的const会得到相同的结果。

使用以下代码适用于两个编译器:

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

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

1 个答案:

答案 0 :(得分:1)

你有错误,因为你期待仿函数(对象)但是带空捕获的lambda可以转换为自由函数:

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

请参阅lambda from cppreference

对于问题的 最新 版本,实现是否满足两个编译器:

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

我认为这是gcc编译器错误,gcc需要这个auto局部变量才能正常工作......

BTW,一个问题 - clang中的一个bug,gcc中的一个 - 我真的建议你找到更简单的方法来实现你的目标 - 也许考虑只使用std::function而不是相当新鲜的泛型lambda?