#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";
}
这段代码期望输出1
,但却抛出了错误:
*项目);
问题是:为什么这不起作用,因为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;
}
问题是,当指定的折叠表达式为空展开时,(... * items)
在编译时无效;即使它在运行时也不会被求值。
可以使用constexpr if (c++ 17起);当指定了一个空展开的折叠表达式时,else部分将被丢弃。
如果值为true,则丢弃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);
}
}
对于空序列,只有&&
(默认为true
),||
(默认为false
)和,
(默认为void()
)具有默认值。
就语言而言,*
没有默认值。但在这种情况下,我们可以使用二元折叠而不是一元折叠:
template<std::size_t... items>
constexpr std::size_t fold_mul()
{
return (1 * ... * items);
}
此操作适用于空情况(值仅为1
)和非空情况(由于1
是乘法的单位元素,因此不改变值)。