将对静态存储 cstyle 数组的引用从 constexpr 函数传递到另一个 constexpr 函数

Pass reference to a static storage cstyle array from on constexpr function to another constexpr function

本文关键字:函数 constexpr 另一个 引用 静态 存储 cstyle 数组      更新时间:2023-10-16

我无法将全局 cstyle 数组传递给 C++14 的 constexpr 函数。我有一个这样的数组:

static const char t[] = "sometext";

我有两个功能:

template <typename T, typename U, std::size_t N>
constexpr static auto count(T (&arr)[N], const U &val)
{
    auto cnt = 0;
    auto it(std::cbegin(arr));
    while (it != std::cend(arr))
    {
        if (*it == val)
            cnt++;
        it++;
    }
    return cnt;
}
template <typename T, std::size_t N> constexpr static auto count_wrapper(T (&arr)[N])
{
    constexpr auto num_elems(count(arr, ','));
    return num_elems;
}

当我像这样调用第一个函数时:

std::cout << count(t, ',') << std::endl;

我可以编译代码并运行它,但是当我像这样调用第二个函数时:

count_wrapper(t);

我收到一个错误:

main.cpp:在"constexpr auto"的实例化中 t(T (&)[N]) [T = 常量字符;长 无符号 int N = 46]':main.cpp:51:53:从这里需要 main.cpp:40:35:在 constexpr 中扩展 'count((* & arr), ',')' main.cpp:40:20: 错误: 'arr' 不是一个常量 表达 constexpr auto num_elems(count(arr, ',') + 1);

参数不是/不能constexpr。(constexpr函数可以在非 constexpr 上下文中使用)。

请注意,std::cout << count(t, ',') << std::endl; 可能会在运行时计算。 您将需要

constexpr auto c = count(t, ',');
std::cout << c << std::endl;

要有constexpr评估保证。

如果适用,可以将值包装在类型中。

template <typename T, T ... cs, typename U>
constexpr static auto count(std::integer_sequence<T, cs...>, const U &val)
{
    const T arr[] = {cs...};
    auto cnt = 0;
    auto it(std::cbegin(arr));
    while (it != std::cend(arr))
    {
        if (*it == val)
            cnt++;
        it++;
    }
    return cnt;
}
auto sometext = std::integer_sequence<char,
                                      's', 'o', 'm', 'e', 't', 'e', 'x', 't' /*, ''*/>;
constexpr auto num_elems(count(sometext, ','));

什么是num_elems?如果是花哨的初始化,那么整个代码可以"重写"如下:

#include <cstdint>
#include <iterator>
const char t[] = "sometext";
template <typename T, typename U, std::size_t N>
constexpr auto count(const T (&arr)[N], const U &val)
{
    std::size_t cnt = 0;
    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    {
        if (*it == val)
            cnt++;
    }
    return cnt;
}
template <typename T, std::size_t N> 
constexpr auto count_wrapper(const T (&arr)[N])
{
    auto const num_elems = count(arr, 'e');
    return num_elems;
}
int main()
{
    constexpr auto x = count_wrapper(t);
    return static_cast<int>(x);
}

这将正确编译和运行。我,更改为e,因此它会计算一些元素。我还while更改为循环for。我也确实将auto cnt更改为std::size_t cnt

注意由于automain中的x类型是size_t

https://gcc.godbolt.org/z/3cdTzr