可变参数模板与使用元组在参数中添加不同的数据对
variadic templates vs using tuples for adding different data pairs in an argument
以下主代码工作正常
string hello = "Hello ";
string world = "templates!";
cout << "var template add: ";
cout << setprecision(2) <<
var_template_add(5, 4, 5.5, 4.0);
用于以下模板生成器代码和可变参数函数
template <typename T>
auto add(T a, T b) {
return a + b;
}
template <typename T, typename... Rest>
auto var_template_add(T first, T second, Rest... others) {
return first + second + add (others...);
}
但是如果再添加两个字符串参数,就像这样
var_template_add(5, 4, 5.5, 4.0, hello, world);
被编译器错误捕获,指出"未找到匹配的重载函数"。
再
string hello = "Hello ";
string world = "templates!";
cout << "strings add result: " << setprecision(2) << add(hello, world) << endl;
如果我像下面这样编写模板函数"添加",则可以工作:
template <typename T1, typename T2>
auto add(T1 a, T2 b) {
return a + b;
}
我的问题是,我怎么能做线
var_template_add(5, 4, 5.5, 4.0, hello, world);
无需像上面那样编写另一个 Add 函数即可工作?!
请注意,我可以使用元组来传递此值,但现在,我只想远离。 有什么想法/改进吗?
将std::string
添加到整数值将不起作用,除非您选择使函数显式转换为字符串,例如使用std::stringstream
或std::to_string
。
如果您希望它通过字符串化行为正确运行,则需要更改它以执行某种形式的显式字符串构建。
但是,您至少可以使当前var_template_add
使用任意数量的参数,因为当前定义需要 4 个参数,否则将无法工作。这将允许var_template_add(hello, world)
示例工作。
在 C++11 中,这可以通过使用一些模板递归来完成。这本身不需要添加任何新功能 - 只需重命名现有函数并更改一个即可。
这个想法是递归调用var_template_add
,直到你最终得到 2 个参数,然后将两者加在一起:
// rename'add' to 'var_template_add'. Use this as recursive base-case.
template <typename T, typename U>
auto var_template_add(T first, U second)
-> decltype(first + second)
{
return first + second;
}
// adds first argument and delegates 'second' and 'others...' to the next 'var_template_add'
template <typename T, typename U, typename... Rest>
auto var_template_add(T first, U second, Rest... others)
-> decltype(first + var_template_add(second, others...))
{
return first + var_template_add(second, others...);
}
对于 2 个参数,它将调用第一个重载。对于 3 个或更多参数,它将调用第二个参数,第二个参数将递归调用下一个var_template_add
,直到最终调用第一个。
注意:此答案是因为问题被标记为 C++11 -- 但请注意,您使用没有尾随返回类型的auto
返回类型实际上是 C++14 而不是 C++11。
如果您有 C++17,您可以使用可变参数折叠表达式更轻松地执行此操作:
template <typename T, typename U, typename...Rest>
auto var_template_add(T first, U second, Rest...others)
{
return first + second + (... + others);
}
>编辑:由于 OP 更新了标签以包含c++14
和c++17
,因此您可以使用to_string
或stringstream
和折叠表达式非常轻松地实现字符串化添加行为。为此,我确实推荐了一个不同的函数——因为附加字符串序列在语义上与"添加"值完全不同。
最好的方法可能是使用std::stringstream
,例如:
template <typename...Args>
std::string variadic_add_str(Args&&...args)
{
auto stream = std::string_stream{};
stream << (... << std::forward<Args>(args));
return stream.str();
}
当前调用工作的唯一方法是让var_template_add
返回单个类型,因此它需要是一个字符串。
相反,您可以在函数中编写cout
,因此您只需要:
template <typename T, typename... Rest>
auto var_template_add(T first, T second, Rest... others) {
cout << setprecision(2) << (first + second) << " ";
if constexpr (sizeof...(others)) var_template_add(others...);
}
这是一个演示。
请注意,在 c++17 之前没有if constexpr
,因此在这种情况下,将额外的重载作为基本情况是一个不错的选择。
- 可变参数模板与使用元组在参数中添加不同的数据对
- 如何在OMNET++中添加专门的命令行参数?
- 如何将带有参数的愚蠢函数添加到愚蠢的执行器中?
- 如何使用主参数添加更多堆栈?
- 在C++中,如何将参数添加到"Args&&... args"参数列表中?
- 我如何将4个以上的参数添加到MIPS中的一个函数
- 如何在 c/c++ 中为参数添加选项?(视觉工作室平台2019)
- 将功能参数添加到向量
- 将参数添加到q_object构造函数
- 使用模板参数添加数据
- 如何将模板函数指针作为值参数添加到地图中
- 在指向另一个宏的可变参数宏中为每个参数添加前缀
- 基于模板参数添加成员函数和成员变量
- 仅当数组属于特定类型时,才将模板化参数添加到数组
- 是否为模板类的某些模板参数添加成员
- 如何在不破坏现有代码的情况下将输出参数添加到功能
- 将参数添加到该类别一个向量中包含的类中
- 将 -m32 参数添加到生成文件命令
- C++-不能将默认参数添加到类模板成员的越界定义中
- 在c++预处理器中为参数添加引号