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

时间:2018-11-13 12:33:19

标签: c++ function c++11 templates variadic-templates

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

#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应用于包print的每个元素。我该怎么办?

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

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

1 个答案:

答案 0 :(得分:6)

  

我想做的就是简单地将printall应用于print到   包装物品的每个元素。我该怎么办?

选项-1

根据用户@liliscent和用户@max66的建议, 在C ++ 11 / C ++ 14中,您可以使用以下行为,其行为类似于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)... };
}

选项-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,则只需使用fold expressions。这样可以提供简洁(非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),...);
}