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