variadic function template without formal parameters

我是研究僧i 提交于 2019-12-13 11:34:59

问题


This is what I'm trying to do:

// 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;
}

It doesn't compile:

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 thread shows a way to fix this, but the base case has to be a template. I don't really like it, because as far as I understand I will have to duplicate code that works with T. Is there a way to avoid that?

So far I came up with two solutions (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;
}

http://ideone.com/yyg6y9:

#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;
}

I wonder if there is a better way to do this.


回答1:


Another way is turning the non-template function f into a variadic template function which accepts zero or more template arguments (the other f requires one or more template arguments). Then to avoid ambiguity, SFINAE away this template function when the number of arguments is not zero. Well, a code is better than 1000 words:

#include <type_traits>

template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == 0>::type f() {
}

template <typename T, typename... Ts>
void f() {
    // do something with T
    f<Ts...>();
}



回答2:


Since class templates can be partially specialized, another possibility is to use class templates to do the work, and have your function delegate to them:

template<typename... Ts>
struct caller
{
    static void call() { } // Base case, terminates recursion
};

template<typename T, typename... Ts>
struct caller<T, Ts...>
{
    static void call()
    {
        // Do something with T
        caller<Ts...>::call();
    }
};

template<typename... Ts>
void f() {
    caller<Ts...>::call();
}


来源:https://stackoverflow.com/questions/16758620/variadic-function-template-without-formal-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!