В следующем минимальном примере S::foo
работает, но S::bar
не работает.
Единственная разница - это порядок пакетов параметров Ts
и Us
.
struct FPtr
и S::lol
- лучший обходной путь, который я нашел, но его довольно неудобно использовать на практике.
Почему вывод аргумента для bar
терпит неудачу (тем более, что я явно указал типы, поэтому никакого вывода не должно происходить вообще)? Это ошибка компилятора (встречается с clang++ 3.5
и g++ 4.9
) или по какой-то причине это стандарт?
template<typename ... Ts>
struct FPtr {
FPtr(void (*val)(Ts ...)) : val{val} {}
void (*val)(Ts ...);
};
template<typename ... Ts>
struct S {
template<typename ... Us>
void lol(FPtr<Us ..., Ts ...>) {}
template<typename ... Us>
void foo(void (*)(Ts ..., Us ...)) {}
template<typename ... Us>
void bar(void (*)(Us ..., Ts ...)) {}
};
void f(int, float) {}
void g(float, int) {}
int main() {
S<int> s;
s.lol<float>(FPtr<float, int>(g));
s.foo<float>(f);
s.bar<float>(g);
}
Сообщение об ошибке:
$ clang++ -std=c++14 t27.cpp -Wall -Wextra -pedantic
t27.cpp:31:4: error: no matching member function for call to 'bar'
s.bar<float>(g);
~~^~~~~~~~~~
t27.cpp:18:7: note: candidate template ignored: failed template argument deduction
void bar(void (*)(Us ..., Ts ...)) {}
^
Примечание. Я сообщил об этой ошибке в GCC и LLVM для отслеживания ошибок.