可以在编译时对数组进行索引吗

Can arrays be indexed at compile time?

本文关键字:索引 数组 编译      更新时间:2023-10-16

在对另一个问题的评论中,用户hvd陈述了以下内容:

尽管可以将字符串文本传递给CCD_ 1函数,并且允许对常量中的字符串文字进行数组索引表达式,对constexpr函数参数的索引操作不符合常量表达式的条件。

我没有完全理解这是什么意思。这是否意味着以下代码中的hash_value变量

#include <cstddef>
// Compute the hash of a string literal adding the values of its characters
template<std::size_t N> constexpr std::size_t
hash_string
    ( const char (& s)[N] )
noexcept
{
    std::size_t h = 0;
    // Array indexing happening under the hood
    for ( const auto c : s )
        h += c;
    return h;
}
constexpr auto hash_value = hash_string("Hello, world!");

无法在编译时进行评估?你能详细说明一下引用的评论吗?

我在评论中说的是,你不能有这样的东西

template <int N>
int f();
constexpr int g(int i) {
  return f<i>(); // invalid
}

因为尽管constexpr函数的结果可以是一个常量表达式,但在体内,它的参数不是。constexpr函数可以用常量参数调用,也可以用非常量参数调用。调用者可以决定,C++没有任何类型的函数可以用常数参数调用。

这在你阅读的答案中很重要,因为如果有一个const char (&str)[N]函数自变量,并将str[i]视为函数体中的常量表达式,这会很有用。

这对你的代码来说并不重要。那个代码很好。

我浏览了N3337和N3936的相关章节,在这两个版本的标准中都没有禁止类型的constexpr函数

template<std::size_t N> constexpr std::size_t
hash_string
    ( const char (& s)[N] )
noexcept
{
    return s[0];
}

事实上,它在C++和clang中都以C++11模式编译。我完全不知道"对constexpr函数参数的索引操作不符合常量表达式"的说法是从哪里来的。我在§5.19[expr.const]中找不到任何禁止这样做的内容。