djsp
djsp

Reputation: 2293

Can arrays be indexed at compile time?

In this comment to another question, the user hvd stated the following:

... although string literals can be passed to constexpr functions, and array indexing is allowed on string literals in constant expressions, an indexing operation on a constexpr function parameter doesn't qualify as a constant expression.

I didn't fully understand what was meant. Does it mean that the hash_value variable in the following code

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

cannot be evaluated at compile time? Could you elaborate on the quoted comment and tell if I am right?

Upvotes: 6

Views: 441

Answers (2)

user743382
user743382

Reputation:

What I was saying in that comment was that you cannot have something like

template <int N>
int f();

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

because although the result of a constexpr function can be a constant expression, inside the body, its parameters aren't. A constexpr function may be called with constant or with non-constant arguments, the caller gets to decide, and C++ doesn't have any sort of function that can only be called with constant arguments.

It mattered in the answer you were reading because it would have been useful to have a const char (&str)[N] function argument, and treat str[i] as a constant expression inside the function body.

This doesn't matter for the code you've got. That code is fine.

Upvotes: 3

T.C.
T.C.

Reputation: 137315

I went through the relevant sections of both N3337 and N3936, and nothing in either version of the standard prohibits a constexpr function of the sort

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

And in fact this compiles in both g++ and clang in C++11 mode. I have absolutely no idea where the claim that "an indexing operation on a constexpr function parameter doesn't qualify as a constant expression" came from. I can find nothing in §5.19 [expr.const] that prohibits this.

Upvotes: 2

Related Questions