c++ - 带有空参数包的一元折叠

标签 c++ variadic-templates c++20 fold

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

<source>:19:28: error: fold of empty expansion over operator*
19 | return (... * items);


我的问题是: 为什么这不起作用,因为 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 部分将被丢弃。

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

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

关于c++ - 带有空参数包的一元折叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66132666/

相关文章:

c++ - 如何对派生类进行限制?

c++:交换 vector 和指针失效?

具有默认模板参数的 C++14 变量模板?

用于递归继承的具有类型和非类型参数混合的 C++ 可变参数模板

c++ - 何时在编译时评估constexpr?

c++ - 具有对齐的 unique_ptr 的负载数据

c++ - 使用 [] 运算符时为 "binding reference of type discards qualifiers"

c++ - 在 Java EE Web 应用程序中打开 TCP 套接字

c++ - 具有函数、输入和输出类型的可变参数模板

c++ - 检查保护参数包是否导致程序格式错误?