как инициализировать статический член constexpr из std :: vector <std :: string> в c ++ 11? - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь инициализировать static constexpr std::vector из std::string с внутри моего класса Foo. Позже я буду использовать адрес его элементов.

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, спасибо.

1 Ответ

0 голосов
/ 10 сентября 2018

Я могу жить с 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;

, где fs() - это 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 какФолляows

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

Обратите внимание, что вам нужно вызвать метод data(), который возвращает 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;
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...