Adi*_*arg 0 c++ templates function-templates variadic-templates c++14
我想计算提供给 function 的任意数量的参数的总和sum。假设给予函数的整数将满足operator+.
如果我注释掉该函数sum()(没有参数的函数),则代码无法编译。如果我取消注释,代码会编译并运行,但永远不会命中 function sum()。
我似乎无法理解为什么我们需要有sum()功能,因为我正在使用条件sizeof...(Args)
如果有人能帮助我理解这一点,我会非常感激吗?
/*
int sum()
{
std::cout << "Sum with 0 Args" << std::endl;
return 0;
}
*/
template <typename T, typename...Args>
T sum(T first, Args...args)
{
// std::cout << sizeof...(Args) << std::endl;
if (sizeof...(Args) != 0)
{
return first + sum(args...);
}
else
{
std::cout << "Found 0 args" << std::endl;
return first;
}
}
int main()
{
std::cout << sum(1, 2, 3) << std::endl;
std::cout << sum(1.2, 3.5) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一旦我取消注释函数 sum(),我就会得到以下输出 -
Found 0 args
6
Found 0 args
4.7
Run Code Online (Sandbox Code Playgroud)
基本上sum()永远不会被调用,这是预期的,但是为什么我们首先需要它呢?
\n\n基本上
\nsum()永远不会被调用,这是预期的,但是为什么我们首先需要它呢?
当您使用普通if语句时,就像在代码中一样,两个分支都会被检查,并且两个分支都必须是可编译的。当sum递归调用时,最后一个函数调用不带参数。为了使这种情况成立,编译器需要一个sum不带参数的函数。
另一方面,从c++17开始,我们有了if constexpr,通过它我们可以在编译时只保留真正的分支。这意味着,只需按如下方式更改代码,您就不再需要sum()不带参数的了。
在这里阅读更多内容:和之间的区别?if constexprif
template <typename T, typename...Args>\nT sum(T first, Args...args) \n{\n if constexpr (sizeof...(Args) != 0) \n // ^^^^^^^^^^\n {\n // .... as before\n }\n else {\n // .... as before\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n但是,在c++11或c++14sum中,您可以通过稍微棘手/ hacky \xe2\x80\xa0 折叠表达式来实现单个功能:
#include <type_traits> // std::common_type\n\ntemplate <typename...Args>\nauto sum(Args...args) -> typename std::common_type<Args...>::type\n{\n using unused = int[];\n typename std::common_type<Args...>::type total{};\n return static_cast<void>(unused{ 0, (total += args, 0)...}), total;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\xe2\x80\xa0参考文献:
\n