To właśnie staram się robić:o zmiennej liczbie argumentów funkcja szablon bez parametrów formalnych
// base case
void f() {}
template <typename T, typename... Ts>
void f() {
// do something with T
f<Ts...>();
}
int main() {
f<int, float, char>();
return 0;
}
To nie kompiluje:
prog.cpp: In instantiation of ‘void f() [with T = char; Ts = {}]’:
prog.cpp:6:5: recursively required from ‘void f() [with T = float; Ts = {char}]’
prog.cpp:6:5: required from ‘void f() [with T = int; Ts = {float, char}]’
prog.cpp:10:25: required from here
prog.cpp:6:5: error: no matching function for call to ‘f()’
prog.cpp:6:5: note: candidate is:
prog.cpp:4:6: note: template<class T, class ... Ts> void f()
prog.cpp:4:6: note: template argument deduction/substitution failed:
prog.cpp:6:5: note: couldn't deduce template parameter ‘T’
This wątek pokazuje sposób, aby rozwiązać ten problem, ale przypadek podstawowy musi być szablonem. Nie podoba mi się to, ponieważ o ile rozumiem, będę musiał zduplikować kod, który działa z T. Czy istnieje sposób, aby tego uniknąć?
Dotychczas wymyśliłem dwóch rozwiązań (http://ideone.com/nPqU0l):
template <typename...> struct types_helper {};
// base case
void f(types_helper<>) {}
template <typename T, typename... Ts>
void f(types_helper<T, Ts...>) {
// do something with T
f(types_helper<Ts...>());
}
int main() {
f(types_helper<int, float, char>());
return 0;
}
#include <type_traits>
struct end_of_list;
template <typename T>
void f() {
static_assert(std::is_same<T, end_of_list>::value, "error");
}
template <typename T1, typename T2, typename... Ts>
void f() {
// do something with T
f<T2, Ts...>();
}
int main() {
f<int, float, char, end_of_list>();
return 0;
}
Zastanawiam się, czy istnieje lepszy sposób to zrobić.
To miło. Chociaż 'enable_if' wydaje się być wadliwy w visual studio, więc musiałem napisać to jak' decltype (typname std :: enable_if :: type()) '. –
catscradle
krótka i łatwa korekta do początkowego kodu, podoba mi się to. –