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