以下主要代码可以正常工作
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);
不像上面那样编写另一个添加函数就可以工作吗?!
请注意,我可以使用元组来传递这个值,但现在,我只想远离它。 有什么想法/改进吗?
当前调用工作的唯一方法是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...);
}
这是一个演示。
请注意,如果constexpr在C++17之前没有,因此在这种情况下,有一个额外的重载作为基本情况是一个不错的选择。
在C++11中,这可以通过使用一些模板递归来完成。 这本身并不需要添加任何新函数--只需重命名一个现有函数并更改一个。
其思想是递归调用var_template_add
,直到最后得到2个参数,然后将这两个参数加在一起:
// rename'add' to 'var_template_add'. Use this as recursive base-case.
template <typename T>
auto var_template_add(T first, T second)
-> decltype(first + second)
{
return first + var_template_add(add, others...);
}
// adds first argument and delegates 'second' and 'others...' to the next 'var_template_add'
template <typename T, typename... Rest>
auto var_template_add(T first, T 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...Rest>
auto var_template_add(T first, T second, Rest...others)
{
return first + second + (... + others);
}
变量模板定义要求变量计数的所有参数具有相同的类型。 即。 你不能把float和string混在一起。 因此,您的函数var_template_add()
需要2个类型为T
的参数,然后需要0个或更多表示为REST
的其他类型的参数,但您需要向它提供2个整数,2个浮点和2个字符串。
注意:变量模板只能接受1个变量数的参数,并且必须位于参数列表的最末尾。 因此,如果您希望能够像在您的示例中那样进行调用,那么您可以将您的模板更改为如下内容例如:
auto var_template_add(T first, T second, R third, R fourth, Rest... others) {//...