C ++ 11:用另一个constexpr char数组初始化constexpr char数组

时间:2019-01-26 20:04:30

标签: c++ arrays c++11 template-meta-programming constexpr

我想用另一个constexpr char[]成员初始化constexpr char []成员。是否可以在C++11或更高版本中进行?

#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;
}

2 个答案:

答案 0 :(得分:2)

  

我想用另一个constexpr char[]成员初始化constexpr char []成员。是否可以在C++11或更高版本中进行?

从C ++ 14开始,您可以使用std::make_index_sequencestd::index_sequence

如果您适合从事ValueOneHolder专业化工作,则可以首先开发一个constexpr函数,给定C样式的数组,该函数将返回数组的大小

template <typename T, std::size_t N>
constexpr std::size_t getDim (T const (&)[N])
 { return N; }

嵌套,您可以声明ValueOneHolder添加第二个模板参数,其默认值是与T::ValueOne对应的索引序列

template <typename T,
          typename = std::make_index_sequence<getDim(T::ValueOne)>>
struct ValueOneHolder;

最后一个简单的部分:带有初始化的部分专业化

template <typename T, std::size_t ... Is>
struct ValueOneHolder<T, std::index_sequence<Is...>>
 { static constexpr char Value[] = { T::ValueOne[Is] ... }; };

不要忘记struct之外的以下行

template <typename T, std::size_t ... Is>
constexpr char ValueOneHolder<T, std::index_sequence<Is...>>::Value[];

以下是完整的C ++ 14编译示例

#include <utility>
#include <iostream>

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

template <typename T, std::size_t N>
constexpr std::size_t getDim (T const (&)[N])
 { return N; }

template <typename T,
          typename = std::make_index_sequence<getDim(T::ValueOne)>>
struct ValueOneHolder;

template <typename T, std::size_t ... Is>
struct ValueOneHolder<T, std::index_sequence<Is...>>
 { static constexpr char Value[] = { T::ValueOne[Is] ... }; };

template <typename T, std::size_t ... Is>
constexpr char ValueOneHolder<T, std::index_sequence<Is...>>::Value[];

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

如果您想要C ++ 11,则可以开发std::make_index_sequencestd::index_sequence的替代品。

答案 1 :(得分:1)

在此特定示例中,您可以将Value声明为以下内容:

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

请注意,除非您切换到-std = c ++ 17或在源文件中添加以下行,否则GCC将无法链接此示例。

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

使用C ++ 14,还可以制作constexpr字符串(或其子字符串)的constexpr副本,如下例所示:

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{}) {}
};