Search code examples
c++arraysc++11template-meta-programmingconstexpr

C++11: Initialize constexpr char array with another constexpr char array


I would like to initialize constexpr char[] member with another constexpr char [] member. Is it possible to do in C++11 or above?

#include <iostream>

struct Base {
 static constexpr char ValueOne[] = "One";
 static constexpr char ValueTwo[] = "Two";
};

template <typename T>
struct ValueOneHolder {
  static constexpr char Value[] = T::ValueOne; // << How can one initialize this?
};

int main() {
  std::cout << ValueOneHolder<Base>::Value << std::endl;
  return 0;
}

Solution

  • In this particular example you may declare Value as the following:

    template <typename T>
    struct ValueOneHolder {
      static constexpr auto Value = T::ValueOne; // << How can one initialize this?
    };
    

    Please note, GCC will fail to link this example unless you switch to -std=c++17 or add the following lines in a source file.

    constexpr char Base::ValueOne[];
    constexpr char Base::ValueTwo[];
    

    With C++14 it is also possible to make a constexpr copy of a constexpr string (or its substring), as shown in example below:

    template<typename CharT, size_t Size>
    struct basic_cestring {
        using value_type = CharT;
        template<size_t... I> constexpr
        basic_cestring(const char* str, index_sequence<I...>)
          : _data{str[I]...} {}
        inline constexpr operator const CharT* () const { return _data; }
        const CharT _data[Size + 1];
    };
    
    template<size_t Size>
    struct cestring : public basic_cestring<char, Size>  {
        using index = make_index_sequence<Size>;
        constexpr cestring(const char* str)
        : basic_cestring<char, Size>(str, index{}) {}
    };