从可变参数函数将函数应用于参数包的所有元素

Mat*_*nti 4 c++ templates function variadic-templates c++11

考虑以下(不工作!)示例:

#include <iostream>

template <typename type> void print(const type & item)
{
    std :: cout << item << std :: endl;
}

template <typename... types> void printall(const types & ... items)
{
    print(items)...;
}

int main()
{
    printall(1, 2, "hello");
}
Run Code Online (Sandbox Code Playgroud)

这里我有一个函数print,它只是打印出它的参数,以及一个printall接受一组参数的可变参数函数.现在,我想做的是简单地printall应用于print包的每个元素items.我该怎么做呢?

注意:我不是在问如何打印一组值.我知道折叠表达式的存在,我知道我可以把它全部items投入std::cout使用它们.这print只是一个例子,可以是任何函数.

我该怎么做呢?这听起来像是非常简单的事情,但我找不到任何(合理的)语法来做到这一点.

JeJ*_*eJo 8

我想做的是简单地printall应用于print包装物品的每个元素.我该怎么做呢?

选项1

正如用户@liliscent和user @ max66在评论中建议的那样,在C++ 11/C++ 14中,您可以使用以下hacky-way,它在C++ 17中表现得像fold表达式.

SEE HERE

#include <iostream>

template <typename type> void print(const type& item)
{
    std::cout << item << '\n';
}

template <typename... types> 
void printall (const types&... items)
{
    using dummy = int[];
    (void)dummy { 0, (print(items), 0)... };
}
Run Code Online (Sandbox Code Playgroud)

选项 - 2

如果上面看起来不够好,请提供经典的可变参数模板重载作为您和函数之间的包装器/帮助器,以便可以访问每个模板函数参数.printall()print()print()

SEE HERE

#include <iostream>

template <typename Type> void print(const Type& item)
{
    std::cout << item << '\n';  // print each argument
}

namespace helper 
{
    void printall() {}          // nontemplate overload for last call(i.e, no arguments call)

    template<typename FirstArg, typename... Types>
    void printall(const FirstArg& firstItem, Types&&... items)  
    {
        ::print(firstItem);                             // call print() for each argument
        helper::printall(std::forward<Types>(items)...);// calls the same wrapper::printalll()
    }
}

template <typename... Types> void printall(const Types& ... items)
{
    helper::printall(items...); // calls the wrapper::printall()
}
Run Code Online (Sandbox Code Playgroud)

选项 - 3

但是,如果您可以访问C++ 17,只需使用折叠表达式.这提供了干净(非hacky)和少量代码.

SEE HERE

template <typename type> void print(const type& item)
{
    std::cout << item << '\n';
}

template <typename... types> void printall(const types&... items)
{
    (print(items),...);
}
Run Code Online (Sandbox Code Playgroud)

  • 在C++ 11中,一种简洁的方法是`using dummy = int []; (void)dummy {(print(items),0)...};`. (3认同)