首页 > 解决方案 > 如何初始化 std::vector 的静态 constexpr 成员在 C++11 中?

问题描述

我正在尝试在我的班级中初始化 a static constexpr std::vectorof s 。稍后我将使用其元素的地址。std::stringFoo

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,谢谢。

标签: c++c++11staticinitializationconstexpr

解决方案


我可以使用 const 而不是 constexpr。但是没有办法做到这一点有点奇怪

你可以忍受这很好,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;

wherefs()是一个constexpr函数,它返回fakeString给定的 C 样式数组char并使用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()返回 a 的方法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;
 }

推荐阅读