You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++11/14中用constexpr生成pair<char,char>的std::array常量

C++14 实现方案

问题核心是C11/14中std::pair<char, char>的构造函数并非constexpr,同时std::array的编译期初始化支持有限。以下是两种可行的C14实现:

方案1:自定义constexpr Pair替代

#include <array>

// 自定义支持编译期构造的Pair结构
template<typename T1, typename T2>
struct ConstexprPair {
    T1 first;
    T2 second;

    constexpr ConstexprPair(T1 f, T2 s) : first(f), second(s) {}
};

// 编译期生成完整牌组
constexpr auto make_deck() {
    std::array<ConstexprPair<char, char>, 52> deck{};
    const char suits[] = {'S', 'H', 'D', 'C'};
    const char ranks[] = {'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'};
    
    int idx = 0;
    for (int s = 0; s < 4; ++s) {
        for (int r = 0; r < 13; ++r) {
            deck[idx++] = ConstexprPair<char, char>{suits[s], ranks[r]};
        }
    }
    return deck;
}

// 编译期初始化的全局牌组常量
constexpr auto deck = make_deck();

方案2:利用索引序列生成元素(无需自定义Pair)

借助C++14的std::index_sequence,通过聚合初始化构造std::pair(编译期聚合初始化不受构造函数非constexpr限制):

#include <array>
#include <utility>

using Card = std::pair<char, char>;

template<std::size_t... Idx>
constexpr std::array<Card, 52> make_deck_impl(std::index_sequence<Idx...>) {
    const char suits[] = {'S', 'H', 'D', 'C'};
    const char ranks[] = {'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'};
    return {{ {suits[Idx/13], ranks[Idx%13]}... }};
}

constexpr std::array<Card, 52> make_deck() {
    return make_deck_impl(std::make_index_sequence<52>{});
}

constexpr auto deck = make_deck();

C++11 实现方案

C++11无std::index_sequence,且constexpr函数不允许循环,需用递归模板完成编译期初始化:

#include <array>
#include <utility>

using Card = std::pair<char, char>;

// 递归模板生成单个牌元素
template<std::size_t N>
struct DeckGenerator {
    static constexpr Card get() {
        const char suits[] = {'S', 'H', 'D', 'C'};
        const char ranks[] = {'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'};
        return {suits[N/13], ranks[N%13]};
    }

    static constexpr void fill(std::array<Card, 52>& arr) {
        DeckGenerator<N-1>::fill(arr);
        arr[N] = get();
    }
};

// 递归终止条件
template<>
struct DeckGenerator<0> {
    static constexpr Card get() {
        return {'S', 'A'};
    }

    static constexpr void fill(std::array<Card, 52>& arr) {
        arr[0] = get();
    }
};

constexpr std::array<Card, 52> make_deck() {
    std::array<Card, 52> arr{};
    DeckGenerator<51>::fill(arr);
    return arr;
}

constexpr auto deck = make_deck();

代码优化建议
  • 增强类型安全:用枚举替代char表示花色和点数,避免无效值:
    enum class Suit { Spade, Heart, Diamond, Club };
    enum class Rank { Ace, Two, Three, ..., King };
    struct Card { Suit suit; Rank rank; };
    
  • 消除魔法数字:将52、4、13等常量定义为constexpr变量,比如constexpr std::size_t DECK_SIZE = 52;,提升可读性和可维护性。
  • 优先选择简洁实现:C++14及以上版本优先用constexpr函数+循环的写法,模板元编程仅在必要场景使用。
  • 复用std::pair:C++14中可通过聚合初始化在constexpr函数里构造std::pair,无需自定义结构,如方案2所示。

内容的提问来源于stack exchange,提问作者Nemexia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:09:51