inf*_*ero 4 c++ fold variadic-templates c++20
#include <iostream>
#include <utility>
template<std::size_t... items>
constexpr std::size_t count()
{
return std::index_sequence<items...>().size();
}
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
if( count<items...>() == 0 )
{
return 1;
}
else
{
return (... * items);
}
}
int main()
{
std::cout << "Result: " << fold_mul<>() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
此代码预计会输出,1但会引发错误:
<source>:19:28: 错误:运算符 *
19 上的空扩展折叠| 退换货品);
我的问题是:为什么这不起作用,因为 fold_expression 显然在else零件中。
作为参考,此实现有效:
template<typename... Args>
constexpr std::size_t fold_mul();
template<std::size_t... j>
requires (count<j...>() > 0)
constexpr std::size_t fold_mul()
{
return (j * ...);
}
template<>
constexpr std::size_t fold_mul()
{
return 1;
}
Run Code Online (Sandbox Code Playgroud)
唯一具有空序列默认值的折叠表达式是&&(默认为true)、||(默认为false) 和,(默认为void())。
*就语言而言没有默认值。但在这种情况下,我们可以使用二元折叠而不是一元折叠:
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
return (1 * ... * items);
}
Run Code Online (Sandbox Code Playgroud)
这适用于空情况(值只是1)和非空情况(因为1是乘法的单位元素,因此不会更改值)。
问题是,当指定折叠表达式为空扩展时,(... * items)在编译时无效;即使它不会在运行时被评估。
您可以使用constexpr if (C++17 起); 那么当被指定为空扩展的折叠表达式时,else 部分将被丢弃。
如果值为真,则丢弃statement-false(如果存在),否则丢弃statement-true。
template<std::size_t... items>
constexpr std::size_t count()
{
return std::index_sequence<items...>().size();
}
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
if constexpr ( count<items...>() == 0 )
// ^^^^^^^^^
{
return 1;
}
else
{
return (... * items);
}
}
Run Code Online (Sandbox Code Playgroud)