如何在 C++11 中初始化 std::vector<std::string> 的静态 constexpr 成员?

how to initialize a static constexpr member of std::vector<std::string> in c++11?

我正在尝试在 class Foo 中初始化 static constexpr std::vectorstd::string。稍后我将使用其元素的地址。

class Foo {
public:
  static constexpr std::vector<std::string> a = {"a", "bc", "232"}; // not working, constexpr variable not literal ....
  const std::vector<std::string> a = {"a", "bc", "232"}; // this works
}

使用 c++11,谢谢。

I can live with const instead of constexpr. but it's a little bit odd that there's no way to do this

你可以和 const 一起生活很好,但是,为了好玩,我向你展示了一种方法,可以让 constexpr static 成员使用 std::array 而不是 std::vector 和(再次)std::array 而不是 std::string.

很遗憾,您使用的是 C++11,因此没有 std::index_sequence/std::make_index_sequence(从 C++14 开始可用),但我在以下完整内容中添加了 C++11 替代品例如。

如果您知道要在 constexpr 成员中使用的字符串长度的上限,比如 9(在您的示例中为 3),您可以定义一个 fakeString 类型,如下所示

using fakeString = std::array<char, 10u>;

观察 std::array 的大小是最大长度加一(加上最后的零)。

现在你可以定义foo如下

struct foo
 {
   static constexpr std::array<fakeString, 3u> a
    {{ fs("a"), fs("bc"), fs("232") }};
 };

constexpr std::array<fakeString, 3u> foo::a;

其中 fs() 是一个 constexpr 函数,它 return 一个 fakeString 给定一个 char 的 C 样式数组并使用 fsh() 辅助函数

fs()fsh()函数如下

template <std::size_t ... Is, std::size_t N>
constexpr fakeString fsh (indexSequence<Is...> const &, char const (&s)[N])
 { return {{ s[Is]... }}; }

template <std::size_t N>
constexpr fakeString fs (char const (&s)[N])
 { return fsh(makeIndexSequence<N>{}, s); }

现在可以使用foo::a如下

   for ( auto const & fakeS : foo::a )
      std::cout << fakeS.data() << std::endl;

注意你必须调用 data() 方法 return 一个 char *,这是一个 C 风格的字符串。

我重复一遍:只是为了好玩。

下面是一个完整的编译C++11的例子

#include <array>
#include <iostream>

template <std::size_t...>
struct indexSequence
 { using type = indexSequence; };

template <typename, typename>
struct concatSequences;

template <std::size_t... S1, std::size_t... S2>
struct concatSequences<indexSequence<S1...>, indexSequence<S2...>>
   : public indexSequence<S1..., ( sizeof...(S1) + S2 )...>
 { };

template <std::size_t N>
struct makeIndexSequenceH
   : public concatSequences<
               typename makeIndexSequenceH<(N>>1)>::type,
               typename makeIndexSequenceH<N-(N>>1)>::type>::type
 { };

template<>
struct makeIndexSequenceH<0> : public indexSequence<>
 { };

template<>
struct makeIndexSequenceH<1> : public indexSequence<0>
 { };

template <std::size_t N>
using makeIndexSequence = typename makeIndexSequenceH<N>::type;

using fakeString = std::array<char, 10u>;

template <std::size_t ... Is, std::size_t N>
constexpr fakeString fsh (indexSequence<Is...> const &, char const (&s)[N])
 { return {{ s[Is]... }}; }

template <std::size_t N>
constexpr fakeString fs (char const (&s)[N])
 { return fsh(makeIndexSequence<N>{}, s); }

struct foo
 {
   static constexpr std::array<fakeString, 3u> a
    {{ fs("a"), fs("bc"), fs("232") }};
 };

constexpr std::array<fakeString, 3u> foo::a;

int main ()
 {
   for ( auto const & fakeS : foo::a )
      std::cout << fakeS.data() << std::endl;
 }