6

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?

14
  • I don't see anything in C++14 standard that bans this. Your code compiles just fine in clang. Commented Sep 18, 2014 at 16:12
  • Do many compilers make this kind of optimization? That seems very aggressive. Commented Sep 18, 2014 at 16:13
  • @T.C. Yes, it compiles and works fine for me too on Clang. However, and especially since I don't know assembly, I want to ensure that it is evaluated at compile time. Commented Sep 18, 2014 at 16:13
  • @Kalrish If you write constexpr auto foo = ...;, it must be evaluated at compile time. Commented Sep 18, 2014 at 16:14
  • 3
    Some what related question from yesterday Computing length of a C string at compile time. Is this really a constexpr? ... assigning to a constexp variable means is will be evaluated at compile time and I don't see any issues with your code either. Commented Sep 18, 2014 at 16:17

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! Now I understand it: a constexpr function is enabled to be evaluated at compile time, but not required. Thus, it may be used in a context in which constant expressions are required, but it cannot be assumed that it will always run at compile time. That's why constexpr function arguments cannot be evaluated in a static_assert.
+1 (from yesterday) thank you for following up and clarifying.
2

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.

3 Comments

Can the problem be from use of the for loop?
@RSahu That's a C++14 vs. C++11 issue. The loop isn't allowed in C++11 constexpr, but the indexing claim is unrelated to that.
@hvd I would still like to know the reasons for the quoted statement, even after your standard-based explanation. It intrigues me :).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.