https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104358
--- Comment #2 from qingzhe huang <nickhuang99 at hotmail dot com> --- Here are more tests (https://www.godbolt.org/z/5qc8jTGa8) to show that only msvc is giving the correct result. It just illustrates the use cases of this definition and why it should be allowed. 1. By using operator "+", here the type "Lambda" is just a free function pointer. template<typename T> using Lambda=decltype(+[](T){}); static_assert(is_same_v<Lambda<int>, void(*)(int)>); 2. The "foo" takes "Lambda" as parameter template<typename T> T foo(T&&, Lambda<T>); 3. As "Lambda<T>" is just a function pointer, "foo" should allow both free function pointer or lambda(by conversion operator) to be used as argument. And because GCC mistakenly consider "foo<int>" signature as "int(*)(int&&, /*Lambda<int>*/int)", this is not possible. static_assert(is_same_v<decltype(&foo<int>), int(*)(int&&, int)>); These are use cases for "foo": a) using lambda directly foo<int>(5, [](int n){});// lambda conversion operator! b) using converted function pointer from lambda by operator "+" auto funptr=+[](int n){}; foo<int>(5, funptr); c) directly using a function pointer void(*ptr)(int)=funptr; foo<int>(5, ptr);