-1

The following code initializes two const strings during compilation time:

class Test
{
public:
    static constexpr const char* LOS = "Los ";
    static constexpr const char* ANGELES = "Angeles";
};

How to create another constant string (const char* or const std::string) as the concatenation of the two constant strings? Adding the following line

static constexpr const std::string LOS_ANGELES = std::string(LOS).append(ANGELES);

emits the error:

error: the type ‘const string {aka const std::basic_string<char>}’ of constexpr variable ‘Test::LOS_ANGELES’ is not literal
xuhdev
  • 8,018
  • 2
  • 41
  • 69
  • Related to [constexpr-to-concatenate-two-or-more-char-strings](http://stackoverflow.com/questions/28708497/constexpr-to-concatenate-two-or-more-char-strings) – Jarod42 Oct 29 '16 at 22:43

2 Answers2

5

You cannot instanciate a constexpr std::string.

cppreference states that, as for C++11, a constexpr variable requires its type to be a LiteralType. A LiteralType has a trivial destructor, but std::string's destructor is non-trivial.

You can use macros. That's ugly, but it works.

#define MLOS "Los "
#define MANGELES "Angeles"

class Test
{
public:
    static constexpr const char* LOS = MLOS;
    static constexpr const char* ANGELES = MANGELES;
    static constexpr const char* LOSANGELES = MLOS MANGELES;
};

Maybe this answer can help you further.

Community
  • 1
  • 1
asu
  • 1,875
  • 17
  • 27
1

I do not believe std::string's constructors are constexpr, so I think this is not possible. However, you can simulate it:

template<int LENGTH>
struct CES {
  static constexpr auto size = LENGTH;
  char data[LENGTH];
};

template<int N>
constexpr auto make_ces(const char (&v)[N]) {
  CES<N-1> result {};
  for (int i = 0; i < N-1; ++i) {
    result.data[i] = v[i];
  }
  return result;
}

template<int L1, int L2>
constexpr CES<L1+L2> operator+(const CES<L1>& x, const CES<L2>& y) {
  CES<L1+L2> result{};
  for (int i = 0; i < L1; ++i) {
    result.data[i] = x.data[i];
  }
  for (int i = 0; i < L2; ++i) {
    result.data[L1+i] = y.data[i];
  }
  return result;
}

constexpr auto LOS = make_ces("Los");
constexpr auto ANGELES = make_ces("Angeles");
constexpr auto LOS_ANGELES = LOS + ANGELES;

static_assert(LOS_ANGELES.data[2] == 's', "ok");
jbapple
  • 3,297
  • 1
  • 24
  • 38
  • Your `CES` is leaving out the null terminator, which will result in non-strings. – nneonneo Oct 30 '16 at 14:09
  • @nneonneo I agree. They are really more like character arrays than strings. However, as you probably figured out, only a small change would be necessary to make them null-terminated. – jbapple Oct 30 '16 at 16:33