首页 > 解决方案 > 具有空参数包的一元折叠

问题描述

#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,但会引发错误:


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

标签: c++variadic-templatesc++20fold

解决方案


问题是,当指定带有空扩展的折叠表达式时,(... * items)在编译时无效;即使它不会在运行时进行评估。

您可以使用constexpr if (C++17 起); 那么当指定带有空扩展的折叠表达式时,else-part 将被丢弃。

如果值为 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);
    }
}

推荐阅读