20

The "first attempt" doesn't compile while the second does. Why? What's the difference?

First attempt:

#include <iostream>

int main()
{
    constexpr const char text2[] = "hello";
    constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression
    std::cout << b << std::endl;
}

Second attempt:

#include <iostream>
int main()
{
constexpr const char * text1 = "hello";
constexpr const char * a = &text1[4];
std::cout << a << std::endl;

return 0;
}

I compile with (g++ version 4.9.2)

g++ -std=c++11 -o main *.cpp

which gives following error

main.cpp: In function 'int main()':
main.cpp:7:40: error: '& text2[4]' is not a constant expression constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression  
davejal
  • 6,009
  • 10
  • 39
  • 82
Lukáš Bednařík
  • 2,578
  • 2
  • 15
  • 30

1 Answers1

26

From the draft C++11 standard section 5.19 [expr.const] we can see an address constant expression is (emphasis mine gong forward):

[...] a prvalue core constant expression of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t.

In your first case although "hello" is a string literal which has static storage duration. It is copied into an array text2 which does not have static storage duration.

While in your second case text1 is a pointer to a string literal which has static storage duration.

Changing your first example to make text2 static (see it live):

constexpr char static text2[] = "hello";
               ^^^^^^

we no longer get an error.

We can see a string literal has static storage duration from section 2.14.5 [lex.string]:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Does `const` make a `constexpr` more constant? – edmz Nov 13 '15 at 15:29
  • @black no, they have [different roles](http://stackoverflow.com/a/27850923/1708801) for `text2` it is not needed but for the pointers it is. – Shafik Yaghmour Nov 13 '15 at 18:05
  • 3
    Had to think about it, might as well write it out: in the case of `text2`, the array gets initialized from the string literal, but the array is a per-instance copy of the string, so taking the address of its fifth element points to a different location in every instance and that is not a constant expression. in the case of `text1`, the string literal is placed in static space and `text1` is set to the same address in every instance of the class, so taking the address of the fifth element points to the same location in every instance and that is a constant expression. – Blair Houghton Nov 14 '15 at 16:20
  • @BlairHoughton that is a good point, I actually realized later on that pointing that out may be helpful. Thank you for making the comment. – Shafik Yaghmour Nov 14 '15 at 19:23