Próbuję napisać funkcję, która ma inną funkcję, używając pakietów parametrów i niektórych standardowych reguł dopasowania. Jako przykład:Reguły dopasowania pakietów parametrów z wieloma pakietami
template <typename... TListElems, typename... TVectorElems>
void goal(void (*fn)(std::list<TListElems>..., std::vector<TVectorElems>...));
W celu disambiguate TListElems
i TVectorElems
, dodałem kilka std::tuple<T...>*
więc dzwoniący może być jawne:
template <typename... TListElems, typename... TVectorElems>
void foo(std::tuple<TListElems...>*,
std::tuple<TVectorElems...>*,
void (*)(std::list<TListElems>..., std::vector<TVectorElems>...))
{
// blah blah blah
}
void bar(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>)
{
// blah blah blah
}
int main()
{
foo((std::tuple<int, unsigned>*) nullptr,
(std::tuple<float, double>*) nullptr,
&bar);
}
Clang szczęśliwie kompiluje to w sposób chciałbym oczekiwać, natomiast g ++ (7.2.1) daje błąd kompilacji:
matching.cpp: In function ‘int main()’:
matching.cpp:20:13: error: no matching function for call to ‘foo(std::tuple<int, unsigned int>*, std::tuple<float, double>*, void (*)(std::list<int>, std::list<unsigned int>, std::vector<float>, std::vector<double>))’
&bar);
^
matching.cpp:6:6: note: candidate: template<class ... TListElems, class ... TVectorElems> void foo(std::tuple<_Tps ...>*, std::tuple<_Elements ...>*, void (*)(std::list<TListElems>..., std::vector<TVectorElems>...))
void foo(std::tuple<TListElems...>*,
^~~
matching.cpp:6:6: note: template argument deduction/substitution failed:
matching.cpp:20:13: note: mismatched types ‘std::vector<TVectorElems>’ and ‘std::list<int>’
&bar);
^
w main
, chciałbym spodziewać wywołanie foo
wydedukować TListElems
jak <int, unsigned>
i TVectorElems
jako <float, double>
, prowadząc fn
być typu void (*)(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>)
(sposób rzeczy działają, gdy istnieje tylko jeden pakiet lub gdybym ręcznie napisany przeciążenie).
§14.8.2.5/10 jest najbliższy Standard przychodzi jawnie zapobiegając przykład foo
z pracy:
[Note: A function parameter pack can only occur at the end of a parameter-declaration-list (8.3.5). -end note]
std::list<TListElems>...
trochę fn
Wygląda na to naruszałoby tę notatkę, ale to nie jest do końca jasne .
Pytanie brzmi: Kto ma rację? GCC, Clang, czy coś innego?
§17.9.2.5/6 podaje powód, dla którego działa rozwiązanie Jarod42 (w szczególności: "Jeśli typ jest określone jako 'void f (nazwa_typowa A :: B, A )', 'T' w' A :: B' nie jest wydedukowane, ale 'T' w' A 'jest wydedukowane "), ale jest dla mnie dwuznaczne, jeśli Clang lub GCC rzeczywiście ma właściwą interpretację. –