带空参数包的一元折叠


#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,但却抛出了错误:

: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;
}

问题是,当指定的折叠表达式为空展开时,(... * 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是乘法的单位元素,因此不改变值)。

相关内容

  • 没有找到相关文章

最新更新