具有嵌套可变参数模板的函数

时间:2014-05-10 23:45:21

标签: c++ templates variadic-templates

您是否可以使用可变参数模板编写函数,该模板接受任意元组列表,每个元组都有一组不同的参数?所以你会有类似的东西:

template< /* some crazy variadic thing...*/ >
void func( ... ) {}

func(make_tuple(1,2), make_tuple("hello"));
SFINAE救援! 把Jeffery的答案进一步深入,我写了这个小片段。您可以将fuples以外的类型放在func的参数列表中的任何位置,它将编译并运行,当它遇到第一个不是模板类的类型时,它将打破我的打印链。 seqgens来自here

template<typename T>
int print(T& t) {
        cout << t << " ";
        return 0;
}

template<typename... T> void dumby(T...) {}

// so other template classes don't cause error (see bar below)
template<typename... A>
void expand(A... a) {}

template<typename... A, int... S>
void expand(tuple<A...> a, seq<S...>) {
        dumby(print(get<S>(a))...);
        cout << endl;
}

template<class... Types>
void func(Types...) {}

template<template<typename...> class A, class... Types, class... tup_types>
void func(A<tup_types...> a, Types... args) {
        expand(a, typename gens<sizeof...(tup_types)>::type());

        func(args...);
}

template<typename... A> struct bar {};

int main () {
        func(make_tuple(0,1), make_tuple(2), 1, make_tuple("hello"), 0);
        func(make_tuple(0,1), bar<int,int>(), make_tuple(2), 1, make_tuple("hello"), 0);
}

我必须找到一个实用的用例来尝试它,但我会称之为试探性的成功!

2 个答案:

答案 0 :(得分:3)

这是不可能的。有可能强制参数的类型与static_assertstd::enable_if相同,但std::tuple的不幸现实是它是一个类模板,因此可以,生成多种不同的类型。

最好的方法是使用SFINAE。例如:

template<class A>
void func(A a) {
    std::cout << "First of last: " << std::get<0>(a) << '\n';
}

template<class A, class... Types>
void func(A a, Types... args) {
    std::cout << "First of element: " << std::get<0>(a) << '\n';
    func(args...);
}

Live demo

以上示例will succeed当所有元素都是元组时,but fail当它们不是元素时。{/ p>

答案 1 :(得分:3)

是的,只需使用带有元组的基函数,然后使用可变参数模板/参数创建相同名称的函数。

template<typename ... Types>
void func(const std::tuple<Types...> &Tuple){
    // work with tuple
}

template<typename TupleType, typename ... TupleTypes>
void func(const TupleType &arg, const TupleTypes &... args){
    func(arg);
    func(args...);
}

int main(){
    func(std::make_tuple(1, 2), std::make_tuple("hello"));
}

这会为您提供很大的灵活性,因为您可以了解tuplethrowstatic_assert中的类型数量,或者当您遇到某些内容时#39; t或者OR你可以更进一步,在函数上使用std::enable_if只允许元组的某些条件!

此函数仅适用于std::tuple,但您可以进一步扩展它以允许使用任何容器,通过将第一个函数更改为:为其类型提供多个模板参数:

template<typename ... Types, template<typename...> class TupleType>
void func(const TupleType<Types...> &Tuple){
    // Work with any type inter-face-able like a tuple
}