C++ 可变模板与使用元组在参数中添加不同数据对的比较
以下主要代码可以正常工作C++ 可变模板与使用元组在参数中添加不同数据对的比较,c++,c++14,c++17,variadic-templates,generic-programming,C++,C++14,C++17,Variadic Templates,Generic Programming,以下主要代码可以正常工作 string hello = "Hello "; string world = "templates!"; cout << "var template add: "; cout << setprecision(2) << var_template_add(5, 4, 5.5, 4.0); 被编译器错误捕获,称未找到匹配的
string hello = "Hello ";
string world = "templates!";
cout << "var template add: ";
cout << setprecision(2) <<
var_template_add(5, 4, 5.5, 4.0);
被编译器错误捕获,称未找到匹配的重载函数
再说一遍
string hello = "Hello ";
string world = "templates!";
cout << "strings add result: " << setprecision(2) << add(hello, world) << endl;
在没有像上面那样编写另一个add函数的情况下工作
请注意,我可以使用tuple传递这个值,但现在,我只想远离它。有什么想法/改进吗?当前调用工作的唯一方法是var\u template\u 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,因此在这种情况下,将额外的重载作为基本大小写是一个不错的选择。当前调用工作的唯一方法是让var\u template\u 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,因此在这种情况下,将额外的重载作为基本大小写是一个不错的选择。除非您选择使函数显式转换为字符串,例如使用std::stringstream或std::to_字符串,否则将std::string添加到整数值将不起作用
如果希望它在字符串化行为中正确运行,则需要对其进行更改,以进行某种形式的显式字符串构建
但是,您至少可以使当前的var_template_add使用任意数量的参数,因为当前定义需要4个参数,否则将无法工作。这将允许var_模板_addhello,世界示例工作
在C++11中,这可以通过使用一些模板递归来完成。这不需要添加任何新函数本身——只需重命名现有函数并修改一个即可
其思想是递归调用var_template_add,直到得到两个参数,然后将这两个参数相加:
//将“添加”重命名为“变量模板添加”。将其用作递归基本情况。
样板
自动变量模板添加第一,第二
->decltypefirst+second
{
返回第一个+第二个;
}
//将第一个参数和委托“second”和“others…”添加到下一个“var\u template\u add”
样板
自动变量模板添加第一,第二,其余。。。其他
->decltypefirst+var\u template\u addsecond,其他。。。
{
返回第一个+变量模板添加第二个,其他。。。;
}
对于2个参数,它将调用第一个重载。对于3个或更多参数,它将调用第二个参数,该参数将递归地调用下一个var_template_add,直到最终调用第一个参数
注意:这个答案是因为问题被标记为C++11-但是请注意,您使用的自动返回类型没有尾随返回类型实际上是C++14,而不是C++11
如果您有C++17,则使用可变折叠表达式可以更轻松地执行此操作:
样板
自动变量模板添加第一,第二,其余…其他
{
返回第一个+第二个+…+其他;
}
编辑:
由于OP将标记更新为包含c++14和c++17,因此可以使用to_string或stringstream以及折叠表达式非常轻松地实现字符串化添加行为。对于这一点,我建议使用不同的函数,因为追加字符串序列在语义上与添加值是完全不同的操作
最好的方法可能是使用std::stringstream,类似于:
样板
std::字符串变量_add _strArgs&&…args
{
auto stream=std::string_stream{};
stream除非您选择将函数显式转换为字符串,例如使用std::stringstream或std::to_字符串,否则将std::string添加到整数值将不起作用
如果希望它在字符串化行为中正确运行,则需要对其进行更改,以进行某种形式的显式字符串构建
但是,您至少可以使用任意数量的参数使当前的var\u template\u add工作,因为当前定义需要4个参数,否则它将无法工作。这将允许var\u template\u addhello(世界示例)工作
在C++11中,这可以通过使用一些模板递归来实现。这本身不需要添加任何新函数——只需重命名现有函数并修改它即可
其思想是递归调用var_template_add,直到得到两个参数,然后将这两个参数相加:
//将“add”重命名为“var\u template\u add”。将其用作递归基本情况。
样板
自动变量模板添加第一,第二
->decltypefirst+second
{
返回第一个+第二个;
}
//将第一个参数和委托“second”和“others…”添加到下一个“var\u template\u add”
样板
自动变量模板添加第一,第二,其余…其他
->decltypefirst+var\u template\u addsecond,其他。。。
{
返回第一个+变量模板添加第二个,其他。。。;
}
对于2个参数,它将调用第一个重载。对于3个或更多参数,它将调用第二个重载,即
h将递归地调用下一个var_template_add,直到最终调用第一个
注意:这个答案是因为问题被标记为C++11-但是请注意,您使用的自动返回类型没有尾随返回类型实际上是C++14,而不是C++11
如果您有C++17,则使用可变折叠表达式可以更轻松地执行此操作:
样板
自动变量模板添加第一,第二,其余…其他
{
返回第一个+第二个+…+其他;
}
编辑:
由于OP将标记更新为包含c++14和c++17,因此可以使用to_string或stringstream以及折叠表达式非常轻松地实现字符串化添加行为。对于这一点,我建议使用不同的函数,因为追加字符串序列在语义上与添加值是完全不同的操作
最好的方法可能是使用std::stringstream,类似于:
样板
std::字符串变量_add _strArgs&&…args
{
auto stream=std::string_stream{};
流和什么是5+hello?如果你的+运算是关联的,不需要额外的模板函数,很容易产生另一个重载。在C++17中,总是有折叠表达式,根本不需要模板函数。@Evg这不是有意的。因为+运算符一次需要2个参数,所以上面的exp应该是ev计算类似于5+4+5.5,4.0+hello+world,但我想我明白你的意思了。好吧,9+9.5+helloworld是什么?var_template_add…?的预期输出是什么?@Evg我想我明白了。我要尝试重载+op来添加int和string.:D,这样它可以打印18.5helloworld并返回cigie所指的字符串和5+hello?如果+运算是关联的,则不需要额外的模板函数,很容易产生另一个重载。而且在C++17中,总是有折叠表达式,根本不需要模板函数。@Evg这不是有意的。因为+运算符一次需要2个参数,所以上面的exp应该像5+4+5.5一样进行求值,4.0+hello+world但我想我明白你的意思了。好吧,9+9.5+helloworld是什么?var_template_add…?的预期输出是什么?@Evg我想我明白了。我要尝试重载+op来添加一个int和string。:D,这样它就可以打印18.5helloworld并返回cigienThank@cigien指出的字符串。如果我不想使用它呢模板函数中的CUT?!取决于您想要VARTHEMPPLATEAGADD返回的内容。是否返回字符串?由于IF CONTXPRPR,此解决方案是C++ 17,但问题是标记为C++。11@Human-编译器True,甚至没有注意到:p添加了警告。但是它跳过了最后一次添加。这很有趣。例如,var_template_add 5,4,5.5,4.0,见鬼o,世界DOST打印你好你好TimPaTaLeC.CIGIN如果我不想在模板函数中使用CUT,那要看你想用VARTHEMPPLAGEADAUD返回什么。你想返回一个字符串吗?这个解决方案是C++ 17,因为如果是CONTXPRPR,但是这个问题是用C++标记的。11@Human-编译器True,甚至没有注意到:p添加了警告。它跳过了最后一次添加。很有趣。例如,var_template_add 5,4,5.5,4.0,hello,world donst print hello template仍然使用了相同的问题。没有找到重载函数。没有尝试过C++17代码。没有,这两个代码都不能解决所描述的问题。必须测试代码吗?没有使用字符串+int/float输入进行测试,因为运算符+对此不起作用。问题是t同时用于第一个和第二个。如果这两种类型是不同的模板参数,它应该可以正常工作。C++17版本没有此问题,因为我的编写方式不同。@Amaresh我已更新为第二个添加了不同的模板类型,这将修复重载问题。@lem。但是这仍然不能解决字符串不能与int或float一起添加的问题,因为它们之间没有运算符+。这段代码仍然存在相同的问题。没有找到重载函数。没有尝试过C++17代码。没有。这两个代码都不能解决所描述的问题。必须测试代码吗?没有使用字符串+int进行测试/浮点输入,因为它运算符+不适用于此。问题是t同时用于第一个和第二个。如果这两种类型是不同的模板参数,它应该可以正常工作。C++17版本没有此问题,因为我的编写方式不同。@Amaresh我已更新,为第二个添加了不同的模板类型,这将修复重载问题。但这仍然无法解决字符串不能与int或float一起添加的问题,因为它们之间没有运算符+
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);
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...);
}