Take this example: $ cat t28.cpp template<class ... Ts> struct S { template<class ... Us> void foo(void (*)(Us..., Ts ...)) {} }; void f(float, int) {} int main() { S<int>().foo<float>(f); } $ g++-4.9 -std=c++14 t28.cpp t28.cpp: In function ‘int main()’: t28.cpp:10:23: error: no matching function for call to ‘S<int>::foo(void (&)(float, int))’ S<int>().foo<float>(f); ^ t28.cpp:10:23: note: candidate is: t28.cpp:4:7: note: template<class ... Us> void S<Ts>::foo(void (*)(Us ..., Ts ...)) [with Us = {Us ...}; Ts = {int}] void foo(void (*)(Us..., Ts ...)) {} ^ t28.cpp:4:7: note: template argument deduction/substitution failed: t28.cpp:10:23: note: mismatched types ‘int’ and ‘float’ S<int>().foo<float>(f); ^ $ g++-4.9 --version g++-4.9 (Debian 4.9.2-22) 4.9.2 I have reproduced the issue with g++-5.1.0 using https://gcc.godbolt.org/. Note that clang++ has this issue as well, but it works with icc and supposedly even MSVC. The issue can be fixed by swapping the order of Us... and Ts... in the function pointer type, or by replacing the function pointer type by some other type like std::tuple. Related: http://stackoverflow.com/questions/31040075 clang++ error, for completeness: $ clang++-3.7 -std=c++14 t28.cpp t28.cpp:10:11: error: no matching member function for call to 'foo' S<int>().foo<float>(f); ~~~~~~~~~^~~~~~~~~~ t28.cpp:4:7: note: candidate template ignored: failed template argument deduction void foo(void (*)(Us..., Ts ...)) {} ^ 1 error generated. $ clang++-3.7 --version Debian clang version 3.7.0-svn239806-1+b1 (trunk) (based on LLVM 3.7.0) Target: x86_64-pc-linux-gnu Thread model: posix
Clang bug: https://bugs.llvm.org/show_bug.cgi?id=23949
I have a similar problem with only one parameter pack, that I think is closely related to this bug. The following code does not work with gcc 8.1.1, gcc 8.2 and Apple LLVM version 9.1.0, but does work with MSVC 2017 15.8.4 and icc 18.0.0 (as checked with https://godbolt.org) template<typename _Object, typename ..._Parameters> static void whatever(_Object*, void(_Object::*method)(_Parameters..., float)) {} struct Foobar { void myMethod(bool, float); }; int main(int argc, char** argv) { Foobar f; whatever<Foobar, bool>(&f, &Foobar::myMethod); } When compiled with -std=c+=14, gcc's output is: <source>: In function 'int main(int, char**)': <source>:10:49: error: no matching function for call to 'whatever<Foobar, bool>(Foobar*, void (Foobar::*)(bool, float))' whatever<Foobar, bool>(&f, &Foobar::myMethod); ^ <source>:2:13: note: candidate: 'template<class _Object, class ... _Parameters> void whatever(_Object*, void (_Object::*)(_Parameters ..., float))' static void whatever(_Object*, void(_Object::*method)(_Parameters..., float)) {} ^~~~~~~~ <source>:2:13: note: template argument deduction/substitution failed: <source>:10:49: note: mismatched types 'float' and 'bool' whatever<Foobar, bool>(&f, &Foobar::myMethod); ^ Note that the following version of the above code DOES work perfectly, on all aforementioned mentioned compiler versions. template<typename _Object, typename ..._Parameters> static void whatever(_Object*, void(_Object::*method)(float, _Parameters...)) {} struct Foobar { void myMethod(float, bool); }; int main(int argc, char** argv) { Foobar f; whatever<Foobar, bool>(&f, &Foobar::myMethod); } The difference is that in the first version, the parameter pack comes first, and then the fixed float parameter, while in the second version, the float comes first, and then the parameter pack. Hope this helps
This still affects g++ 9.2.1. clang fixed this between 6.0.0 and 7.0.0, icc 13 and msvc 19 also work. This has nothing to do with class functions: static void foo( int, int ) { } template <typename... T> void bar1( void ( * )( int, T... ) ) { } template <typename... T> void bar2( void ( * )( T..., int ) ) { } int main() { bar1<int>( foo ); bar2<int>( foo ); } Because we have twice "int" in foo, the error message is slightly different: arg_deduct.cc: In function ‘int main()’: arg_deduct.cc:11:18: error: no matching function for call to ‘bar2<int>(void (&)(int, int))’ 11 | bar2<int>( foo ); | ^ arg_deduct.cc:7:6: note: candidate: ‘template<class ... T> void bar2(void (*)(T ..., int))’ 7 | void bar2( void ( * )( T..., int ) ) { } | ^~~~ arg_deduct.cc:7:6: note: template argument deduction/substitution failed: arg_deduct.cc:11:18: note: candidate expects 1 argument, 2 provided 11 | bar2<int>( foo ); | ^ The analogous construction with classes works like charm: template <typename...> struct Foo {}; static Foo<int, int> foo; template <typename... T, template<typename...> typename C> void bar1( C<int, T...> ) {} template <typename... T, template<typename...> typename C> void bar2( C<T..., int> ) {} int main() { bar1<int>( foo ); bar2<int>( foo ); }
I suspect PR 56190 is very much the same bug.
Also related to PR 83542.