可以在编译时索引数组吗?

时间:2014-09-18 16:05:48

标签: c++ arrays c++14 constexpr constant-expression

this comment to another question中,用户hvd声明了以下内容:

  

...尽管可以将字符串文字传递给constexpr函数,   并且在常量中的字符串文字上允许数组索引   表达式,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!");

无法在编译时进行评估?你能否详细说明引用的评论并告诉我是否正确?

2 个答案:

答案 0 :(得分:3)

我在评论中说的是你不能拥有像

这样的东西
template <int N>
int f();

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

因为虽然constexpr函数的结果可以是常量表达式,但在体内,其参数不是。可以使用常量或非常量参数调用constexpr函数,调用者可以决定,并且C ++没有任何类型的函数,只能 使用常量参数调用

在您正在阅读的答案中,这很重要,因为拥有const char (&str)[N]函数参数会很有用,并将str[i]视为函数体内的常量表达式。

这与您获得的代码无关。那段代码很好。

答案 1 :(得分:2)

我浏览了N3337和N3936的相关部分,并且该标准的任何一个版本都没有禁止排序的constexpr功能

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

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