简体   繁体   English

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

[英]function with nested variadic template

Can you write a function using variadic templates that accepts an arbitrary list of tuples, each with a different set of parameters?您能否使用可变参数模板编写一个函数,该函数接受任意元组列表,每个元组具有不同的参数集? So you would have something like:所以你会有类似的东西:

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

func(make_tuple(1,2), make_tuple("hello"));

SFINAE to the rescue! SFINAE 来救援! Taking Jeffery's answer a little further, I wrote this little snippet.让杰弗里的回答更进一步,我写了这个小片段。 You can put types other than tuples anywhere in the argument list for func and it will compile and run, it will just break my printing chain when it hits the first type that isnt a template class.您可以将元组以外的类型放在 func 的参数列表中的任何位置,它会编译和运行,当它遇到第一个不是模板类的类型时,它只会破坏我的打印链。 seq and gens come from here . seqgens来自这里

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

I'll have to find a practical use case to try it out but I'll call that a tentative success!我必须找到一个实际的用例来尝试它,但我称之为试探性的成功!

Yes, just use a base function taking a tuple then make a function of the same name with variadic templates/parameters.是的,只需使用带元组的基函数,然后使用可变参数模板/参数创建同名函数。

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"));
}

This will give you a lot of flexibility in that you can know the number of types in the tuple and throw or static_assert or whatever you like when you come across something you don't like OR you could go even further and use std::enable_if on the function to only allow certain conditions with your tuples!这将为您提供很大的灵活性,因为您可以知道tuple的类型数量,并在遇到不喜欢的东西时throwstatic_assert或任何您喜欢的东西,或者您可以更进一步使用std::enable_if在函数上只允许元组的某些条件!

This function will only work with std::tuple as you asked, but you could expand it further to allow the use of any container that takes multiple template arguments for it's types by changing the first function to:此函数只能按照您的要求与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
}

EDIT编辑

This can be made a little more terse with C++17 fold expressions :使用C++17 折叠表达式可以更简洁:

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

template<typename ... Tuples>
void func(const Tuples &... tuples){
    (func(tuples), ...);
}

It's not possible.这是不可能的。 It could be possible to enforce that the type of the arguments is the same with a static_assert or an std::enable_if , but the unfortunate reality of std::tuple is that it's a class template and can, therefore, generate multiple different types.可以强制参数的类型与static_assertstd::enable_if ,但std::tuple的不幸现实是它是一个类模板,因此可以生成多种不同的类型。

Your best shot is to make use of SFINAE .你最好的办法是利用SFINAE For example:例如:

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现场演示

The above example will succeed when all the elements are tuples, but fail when they are not.当所有元素都是元组时,上面的示例会成功如果不是,则失败

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM