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

C++14 constexpr编译期计算std::array报错,求正确性判断与替代方案

Answer

First, let's break down your questions clearly:

1. Does your code comply with the C++14 standard?

It depends on the exact implementation of computeIndices, but if it follows C14's constexpr rules (no runtime-only operations, uses allowed constexpr constructs like loops or simple arithmetic), it should be standard-compliant. The MSVC error expression did not evaluate to a constant often comes down to compiler-specific limitations—MSVC was slower to fully roll out C14 constexpr support compared to GCC or Clang. For example, some loop patterns or std::array manipulations that are legal in C++14 might still be treated as non-constant expressions by older MSVC versions.

2. Alternative C++14-compliant implementations

Here are two reliable ways to convert a boolean array to an index sequence at compile time:

Option 1: Template metaprogramming with index sequences

This uses recursive templates to collect indices where the boolean value is true, with zero runtime overhead:

#include <array>
#include <cstddef>
#include <utility>

namespace detail {
    // Recursive helper to gather indices for true values
    template <std::size_t CurrentIdx, bool CurrentBool, bool... RestBools, std::size_t... CollectedIndices>
    constexpr auto build_index_array(std::index_sequence<CollectedIndices...>) {
        if (CurrentBool) {
            return build_index_array<CurrentIdx + 1, RestBools...>(
                std::index_sequence<CollectedIndices..., CurrentIdx>{}
            );
        } else {
            return build_index_array<CurrentIdx + 1, RestBools...>(
                std::index_sequence<CollectedIndices...>{}
            );
        }
    }

    // Termination case for recursion
    template <std::size_t CurrentIdx>
    constexpr auto build_index_array(std::index_sequence<>) {
        return std::array<std::size_t, 0>{};
    }
}

// Public interface: takes a pack of bools and returns the index array
template <bool... Bools>
constexpr auto bools_to_indices() {
    return detail::build_index_array<0, Bools...>(std::index_sequence<>{});
}

// Example usage:
constexpr auto indices = bools_to_indices<true, false, true, true>();
// indices will be std::array<std::size_t, 3>{0, 2, 3}

Option 2: Constexpr functions with compile-time counting

If you're working with a std::array<bool, N> instead of a bool pack, this approach first counts true values at compile time, then builds the index array:

#include <array>
#include <cstddef>

// Count true values in the boolean array (compile-time)
template <std::size_t N>
constexpr std::size_t count_true_values(const std::array<bool, N>& bool_array) {
    std::size_t count = 0;
    for (std::size_t i = 0; i < N; ++i) {
        count += bool_array[i];
    }
    return count;
}

// Build index array using precomputed true value count
template <std::size_t N, std::size_t TrueCount = count_true_values(std::array<bool, N>{})>
constexpr std::array<std::size_t, TrueCount> compute_indices(const std::array<bool, N>& bool_array) {
    std::array<std::size_t, TrueCount> result{};
    std::size_t current_idx = 0;
    for (std::size_t i = 0; i < N; ++i) {
        if (bool_array[i]) {
            result[current_idx++] = i;
        }
    }
    return result;
}

// Example usage:
constexpr std::array<bool, 4> bools = {true, false, true, true};
constexpr auto indices = compute_indices(bools);
// indices will be std::array<std::size_t, 3>{0, 2, 3}

Note that for the second option, some older MSVC versions might require you to explicitly pass TrueCount as a template argument (instead of relying on automatic deduction) to avoid the "not a constant expression" error.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:15:38