在C++中,使用模板元编程生成组合列表的最简单方法是什么?

huangapple go评论93阅读模式
英文:

What's the easiest way to generate a list of combinations in C++ using template meta-programming?

问题

我找到了这个Stack Overflow帖子:https://stackoverflow.com/questions/9593787/whats-the-easiest-way-to-generate-a-list-of-combinations-in-c,它告诉我们如何在运行时生成一个大小为N的true/false元组的所有可能组合的列表。

但是,如果我们知道N,我有相同的问题在编译时该如何做呢?我们如何使用模板元编程和模板递归来实现这一点?假设N在编译时已知,且唯一的值是truefalse

为了重新表述主要问题:“通常,你会遇到这样一个问题,属性A可以是true或false,属性B也可以是true或false,依此类推。我们想要测试A为true而B为false的每种组合,以此类推。”

// 假设N为3,那么将生成以下布尔元组
[true,true,true]
[true,true,false]
[true,false,true]
[true,false,false]
[false,true,true]
[false,true,false]
[false,false,true]
[false,false,false]

可能的函数签名可能如下:

template <std::size_t N>
constexpr auto boolean_combinations()

如果可能的话,我想使用C++17或更高版本来实现这个功能。

英文:

I found the SO post: https://stackoverflow.com/questions/9593787/whats-the-easiest-way-to-generate-a-list-of-combinations-in-c, which tells us how to generate at runtime a list of all possible combinations of a true/false tuple of size N.

However, I have the same question at compile-time if we know N. How would we do this with template meta-programming using template recursion? Assume that N is known at compile time and the only values are true, or false.

To restate the main question: "Oftentimes, you have a problem where property A can be either true or false, property B also either true or false, and so on. We want to test every combination of A being true while B being false, and so on."

// Say N is 3, then the following tuple of booleans would be generated
[true,true,true]
[true,true,false]
[true,false,true]
[true,false,false]
[false,true,true]
[false,true,false]
[false,false,true]
[false,false,false]

A possible function signature might look like:

template &lt;std::size_t N&gt;
constexpr auto boolean_combinations()

If possible, I would like to do this using C++17, or later.

答案1

得分: 4

在C++17中,您不需要模板元编程来实现这个功能。一个constexpr函数就可以搞定:

#include <array>

auto constexpr pow2(std::size_t exponent) -> std::size_t {
    return exponent == 0 ? 1 : 2 * pow2(exponent - 1);
}

template<std::size_t N>
constexpr auto boolean_combinations() {
    static_assert(N < sizeof(std::size_t));
    std::array<std::array<bool, N>, pow2(N)> list{}; // 在C++17中需要初始化
    for (auto i = 0; i < list.size(); ++i) {
        for (auto j = 0; j < N; ++j) {
            list[i][j] = static_cast<bool>(i & (1 << j));
        }
    }
    return list;
}

演示

英文:

In C++17, you don't need template metaprogramming for that. A constexpr function can do the trick:

#include &lt;array&gt;

auto constexpr pow2(std::size_t exponent) -&gt; std::size_t {
    return exponent == 0 ? 1 : 2 * pow2(exponent - 1);
}

template&lt;std::size_t N&gt;
constexpr auto boolean_combinations() {
    static_assert(N &lt; sizeof(std::size_t));
    std::array&lt;std::array&lt;bool, N&gt;, pow2(N)&gt; list{}; // initialization needed in C++17
    for (auto i = 0; i &lt; list.size(); ++i) {
        for (auto j = 0; j &lt; N; ++j) {
            list[i][j] = static_cast&lt;bool&gt;(i &amp; (1 &lt;&lt; j));
        }
    }
    return list;
}

Demo

huangapple
  • 本文由 发表于 2023年7月18日 01:19:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76706754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定