4

Following up with this question Having a constexpr static string gives a linker error

In the question, this code wasn't able to compile:

#include <iostream>

struct Test { static constexpr char text[] = "Text"; };

int main()
{
    std::cout << Test::text << std::endl; // error: undefined reference to `Test::text'
}

From the comment, this code is able to compile:

#include <iostream>

struct Test { static constexpr auto text = "Text"; };

int main()
{
    std::cout << Test::text << std::endl;
}

My question is why the auto version works but the array of char version doesn't?

Could you please point out the statement in the standard allowing the second version and disallowing the first?

I took a look at Strange behavior with constexpr static member variable but it seems to be another question.

Community
  • 1
  • 1
Danh
  • 5,916
  • 7
  • 30
  • 45
  • 1
    It is same question and same accepted answer is valid: http://stackoverflow.com/a/28534978/113662 i.e. both versions are ill-formed but compiler is not obliged to reject them and it chooses to accept one of them – Tadeusz Kopec for Ukraine Jan 14 '16 at 15:42
  • 1
    @TadeuszKopec No, the latter isn't ill-formed. – Columbo Jan 14 '16 at 15:47
  • @TadeuszKopec I missed the answer of Sahu, which is the addition to the accepted answer. In Sahu's answer, the literal type was mentioned. And, I misunderstood that, text will be deduced char[] instead of char* – Danh Jan 14 '16 at 15:48
  • @Columbo you are right, the mentioned exception applies here. – Tadeusz Kopec for Ukraine Jan 14 '16 at 15:49

2 Answers2

8

A declaration of a static data member in class is never a definition.
The difference between your examples is that only one requires a definition of text.

The auto version deduces char const*, hence text is only subject to an lvalue-to-rvalue conversion and not odr-used. By contrast, the first code effectively passes text's address, odr-use-ing it - i.e. necessitating a definition.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Yeah, the key is `text` is deduced `char const*` instead of `char[]`. I misunderstood that point. – Danh Jan 14 '16 at 15:50
  • Isn't `const char*` an address? I'm confused. – Lingxi Jan 14 '16 at 15:52
  • @Lingxi No, `const char*` is a pointer type. The object of this pointer type passed to the corresponding `operator<<` overload represents the address of the first `char` in `text`, though. – Columbo Jan 14 '16 at 15:58
  • 1
    Oh I see. In the second version, no address-taking operation. In the first version, array-to-pointer conversion involves address taking and is thus ODR-use. – Lingxi Jan 14 '16 at 16:00
  • @Lingxi Well, there are exceptions. For instance, writing `std::cout << Test::text[0];` is not an odr-use, although `text`'s address is implicitly taken. In general, however, that is correct.- – Columbo Jan 14 '16 at 16:03
  • @Columbo In general, the increasing complexity of C++ has blown me away. Really admire your expertise in C++~ – Lingxi Jan 14 '16 at 16:07
2
struct Test { static constexpr auto text = "Text"; };

resolves to

struct Test { static constexpr const char * text = "Text"; };

So the second expression is a constexpr value of a pointer not an array.

Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49