Detecting parameter types from a common lambda compilation error using GCC

I wrote code that extracts types of non-automatic parameters when defining a common lambda function. As you can see in the code below, the idea is to call the connect function with a common lambda and provide arguments for the automatic parameters (which will always be at the beginning in my use case). So in the code below, my goal was to find that the second parameter is of type float.

The code works fine with clang 3.8, but it does not compile with gcc 6.1.1, so I was wondering if this is a bug in gcc or is it just invalid C ++ code? Can I assume that the common lambda is implemented using the templated operator () function, or is it compiler specific?

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

The error that gcc gives is this:

 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); ^ 

Removing const in findArgTypes gives the same result.

Using the following code works with both compilers:

 struct Foo { template <typename T> void operator()(T, float) const {} }; int main() { Foo f; connect(f, 0); } 
+5
source share
1 answer

You have an error because you are expecting a functor (object), but a lambda with an empty grip is converted to a free function:

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

See lambda from cppreference :


For the newest version of your question, the implementation of which satisfies both compilers:

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

I think this is a gcc compiler error that gcc needs the local auto variable to work properly ...

By the way, one question - one mistake in clang, one in gcc - I really advise you to find a simpler way to achieve your goals - perhaps think, just use std::function instead of a completely new generic lambda?

+1
source

All Articles