可变参数模板 - 递归函数 - 最后一个可变参数成员
Variadic Templates - Recursive function - Last variadic member
我有以下代码以及从以下位置复制的可变参数模板:
https://www.youtube.com/watch?v=iWvcoIKSaoc @41:30
auto sum() { return 0; }
template<typename Head, typename... Tail>
auto sum(Head head, Tail... tail)
{
return head+sum(tail...);
}
int main() {
cout<< sum(1,2.4) << endl;
//cout<< sum("hello ", "world") << endl;
return 0;
}
我有两个问题:
1. 此处需要 sum() 函数,以便在处理最后一个可变参数成员时传入 void 的 return 值 - 是否可以避免编写此 sum() 函数并具有相同的功能?
- 从 sum() 函数返回整数“0”会限制整数使用整个模板 - 我可以扩展相同的模板来连接字符串吗?
谢谢
- The
sum()
function is required here so that I can have a return value for a void
passed in when processing the last variadic member - Is it possible to avoid writing this sum()
function and have the same functionality?
每个递归都需要一个停止条件。在典型的使用可变参数模板的递归中(例如在这段代码中),停止条件是主模板的不同重载。所以你不能完全摆脱它。
您当然可以将停止条件替换为其他条件。也许这个,它也适用于对不可默认构造的事物求和:
template <class T>
auto sum(T last) { return last; }
当然,除了递归可变模板之外,还有其他方法;这种方法可能不需要停止条件。
- Returning a integer '0' from the
sum()
function restricts the entire template to be used by integers - Can I extend the same template to concatenate strings?
不,因为非模板函数不知道先前的递归调用正在处理哪种类型。这可以通过使用我上面建议的 "last item" 停止条件来解决。
诀窍是永远不允许空 sum()
调用,并将 sum(last)
视为最后一个递归:
template<typename Last>
auto sum(Last last) {
return last;
}
template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
return head + sum(second, tail...);
}
int main() {
cout<< sum(1,2.4) << endl;
cout<< sum("hello ", "world") << endl;
return 0;
}
为了补充@GuillaumeRacicot 的回答,我更喜欢用 if constexpr
结束递归,这是一个 c++17
特性。
template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
if constexpr(sizeof...(tail) > 0)
return head + sum(second, tail...);
return head + second;
}
也可以考虑折叠表达式:
template<typename ...Pack>
auto sum(Pack... args) {
return (args + ...);
}
我有以下代码以及从以下位置复制的可变参数模板: https://www.youtube.com/watch?v=iWvcoIKSaoc @41:30
auto sum() { return 0; }
template<typename Head, typename... Tail>
auto sum(Head head, Tail... tail)
{
return head+sum(tail...);
}
int main() {
cout<< sum(1,2.4) << endl;
//cout<< sum("hello ", "world") << endl;
return 0;
}
我有两个问题: 1. 此处需要 sum() 函数,以便在处理最后一个可变参数成员时传入 void 的 return 值 - 是否可以避免编写此 sum() 函数并具有相同的功能?
- 从 sum() 函数返回整数“0”会限制整数使用整个模板 - 我可以扩展相同的模板来连接字符串吗?
谢谢
- The
sum()
function is required here so that I can have a return value for avoid
passed in when processing the last variadic member - Is it possible to avoid writing thissum()
function and have the same functionality?
每个递归都需要一个停止条件。在典型的使用可变参数模板的递归中(例如在这段代码中),停止条件是主模板的不同重载。所以你不能完全摆脱它。
您当然可以将停止条件替换为其他条件。也许这个,它也适用于对不可默认构造的事物求和:
template <class T>
auto sum(T last) { return last; }
当然,除了递归可变模板之外,还有其他方法;这种方法可能不需要停止条件。
- Returning a integer '0' from the
sum()
function restricts the entire template to be used by integers - Can I extend the same template to concatenate strings?
不,因为非模板函数不知道先前的递归调用正在处理哪种类型。这可以通过使用我上面建议的 "last item" 停止条件来解决。
诀窍是永远不允许空 sum()
调用,并将 sum(last)
视为最后一个递归:
template<typename Last>
auto sum(Last last) {
return last;
}
template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
return head + sum(second, tail...);
}
int main() {
cout<< sum(1,2.4) << endl;
cout<< sum("hello ", "world") << endl;
return 0;
}
为了补充@GuillaumeRacicot 的回答,我更喜欢用 if constexpr
结束递归,这是一个 c++17
特性。
template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
if constexpr(sizeof...(tail) > 0)
return head + sum(second, tail...);
return head + second;
}
也可以考虑折叠表达式:
template<typename ...Pack>
auto sum(Pack... args) {
return (args + ...);
}