Bug 66670 - "template argument deduction/substitution failed" with function pointers and multiple parameter packs
Summary: "template argument deduction/substitution failed" with function pointers and ...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on: 56190
Blocks: 53506
  Show dependency treegraph
 
Reported: 2015-06-25 15:06 UTC by Michael Enßlin
Modified: 2024-01-20 18:52 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-06-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Enßlin 2015-06-25 15:06:06 UTC
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
Comment 1 Jonathan Wakely 2018-06-21 10:37:50 UTC
Clang bug: https://bugs.llvm.org/show_bug.cgi?id=23949
Comment 2 Marc "Foddex" Oude Kotte 2018-09-13 14:46:02 UTC
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
Comment 3 schlaffi 2019-11-02 20:16:33 UTC
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 );
}
Comment 4 Andrew Pinski 2021-07-27 07:11:21 UTC
I suspect PR 56190 is very much the same bug.
Comment 5 Andrew Pinski 2021-08-23 09:03:38 UTC
Also related to PR 83542.