首页 > 解决方案 > 从可变参数函数将函数应用于参数包的所有元素

问题描述

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

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

在这里,我有一个print简单地打印出其参数的函数,以及一个printall接受一组参数的可变参数函数。现在,我想做的只是简单地printall应用于printpack 的每个元素items。我怎样才能做到这一点?

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

我怎样才能做到这一点?这听起来应该非常简单,但我找不到任何(合理的)语法来做到这一点。

标签: c++functionc++11templatesvariadic-templates

解决方案


我想做的只是简单地printall适用print于包装物品的每个元素。我怎样才能做到这一点?

选项1

正如用户@liliscent和用户@max66在评论中建议的那样,在 C++11/C++14 中,您可以使用以下 hacky-way,其行为类似于C++17 中的折叠表达式

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

选项 - 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()
}

选项 - 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),...);
}

推荐阅读