从可变参数函数将函数应用于参数包的所有元素
Apply function to all elements of parameter pack from a variadic function
考虑以下(无效!)示例:
#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
中。这里print
只是一个例子,可以是任何函数。
我怎样才能做到这一点?这听起来应该非常简单,但我找不到任何(合理的)语法来做到这一点。
What I would like to do is to simply have printall
apply print
to
each element of the pack items. How can I get that done?
选项 - 1
正如用户 @liliscent and user @max66 在评论中建议的那样,
在 C++11/C++14 中,你可以使用以下 hacky-way,它的行为类似于 C++17 中的 fold expressions。
#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()
.
中访问
#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)和更少的代码。
template <typename type> void print(const type& item)
{
std::cout << item << '\n';
}
template <typename... types> void printall(const types&... items)
{
(print(items),...);
}
考虑以下(无效!)示例:
#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
中。这里print
只是一个例子,可以是任何函数。
我怎样才能做到这一点?这听起来应该非常简单,但我找不到任何(合理的)语法来做到这一点。
What I would like to do is to simply have
printall
apply
选项 - 1
正如用户 @liliscent and user @max66 在评论中建议的那样, 在 C++11/C++14 中,你可以使用以下 hacky-way,它的行为类似于 C++17 中的 fold expressions。
#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()
.
#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)和更少的代码。
template <typename type> void print(const type& item)
{
std::cout << item << '\n';
}
template <typename... types> void printall(const types&... items)
{
(print(items),...);
}