【问题标题】:Can arrays be indexed at compile time?数组可以在编译时被索引吗?
【发布时间】:2014-11-13 01:52:00
【问题描述】:

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!");

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

【问题讨论】:

  • 我在 C++14 标准中没有看到任何禁止这一点的内容。您的代码在 clang 中编译得很好。
  • 很多编译器都做这种优化吗?这似乎非常激进。
  • @T.C.是的,它在 Clang 上也可以编译并且对我来说也很好。但是,特别是因为我不知道汇编,我想确保在编译时对其进行评估。
  • @Kalrish 如果你写constexpr auto foo = ...;,它必须在编译时进行评估。
  • 昨天Computing length of a C string at compile time. Is this really a constexpr? ...分配给constexp变量的一些相关问题将在编译时进行评估,我也没有看到您的代码有任何问题。跨度>

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


【解决方案1】:

我在那条评论中说的是你不能拥有类似的东西

template <int N>
int f();

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

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

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

这对于您拥有的代码无关紧要。那个代码很好。

【讨论】:

  • 谢谢!现在我明白了:constexpr 函数启用 可以在编译时进行评估,但不是必需。因此,它可以在需要常量表达式的上下文中使用,但不能假定它总是在编译时运行。这就是为什么不能在 static_assert 中评估 constexpr 函数参数的原因。
  • +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] 中找不到任何禁止这样做的内容。

【讨论】:

  • 问题可能来自使用for 循环吗?
  • @RSahu 这是 C++14 与 C++11 的问题。 C++11 constexpr 中不允许循环,但索引声明与此无关。
  • @hvd 我仍然想知道引用声明的原因,即使在您基于标准的解释之后。这让我很感兴趣 :)。
猜你喜欢
  • 1970-01-01
  • 2020-03-04
  • 2014-01-13
  • 2011-05-02
  • 1970-01-01
  • 2020-10-03
  • 2012-04-09
  • 2015-05-29
相关资源
最近更新 更多