Constexpr строки, создание из C-Style строки

141
24 апреля 2019, 06:00

Сначала дам собственно код:

#define X_ASSERT(CHECK) \
( (CHECK) ? void(0) : []{assert(!#CHECK);}() )    
template <int N, typename CharT>
class string_literal {
    static_assert(N >= 0, "Empty size parametr 'N'!");
    const CharT(&_lit)[N + 1];
public:
    constexpr string_literal(const CharT(&lit)[N + 1])
        :
        _lit((X_ASSERT(lit[N] == CharT('\0')), lit))
    {}
    using char_type = CharT;
    constexpr CharT operator[](int i) const {
        return X_ASSERT(i >= 0 && i < N), _lit[i];
    }
    constexpr std::size_t size() const { return N; }
    constexpr const CharT* c_str() const { return _lit; }
    constexpr operator const CharT*() const { return c_str(); }
    constexpr operator std::basic_string_view<CharT>() const { return { c_str(), size() }; }
};
template <typename CharT>
constexpr int inline str_size(const CharT* str, int size = 0) {
    return (str[0] == CharT('\0')) ? size : str_size(str + 1, size + 1);
}
template <int N, typename CharT>
constexpr decltype(auto) inline literal(const CharT(&lit)[N])
{
    return string_literal<N - 1, CharT>(lit);
}

Вопрос такой код работает:

constexpr auto NAME = simplelogger::utils::literal("NAME");
constexpr auto name = "NAME";
constexpr const char(&ch)[4] = { name[0], name[1] , name[2], name[3]};

но если я добавляю конструктор и функцию для получения строки из с-style:

template <int ...PACK>
constexpr string_literal(const CharT* str, std::integer_sequence<int, PACK...>) 
    :
    _lit{str[PACK]...}
{}
template <int N, typename CharT>
constexpr decltype(auto) inline literal_b(const CharT* str) {
    return string_literal<N, CharT>(str, std::make_integer_sequence<int, N>{});
} 

и создаю таким путем:

constexpr auto var = "VAR";
constexpr auto var_2 = simplelogger::utils::literal_b<simplelogger::utils::str_size(var)>(var); // Должно сработать

то компилятор выводит следующее:

Source.cpp
1>source.cpp(36): error C2131: expression did not evaluate to a constant 
1>stringliteral.hpp(26): note: failure was caused by a read of a variable outside its lifetime
1>stringliteral.hpp(26): note: see usage of '$S2'

Все Note относятся к строке инициализации _lit{str[PACK]...} в новом конструкторе. Как мне реализовать создание string_literal из указателя на с-строку. Компилятор MSVC 2017 последней версии (С++17 включен).

ADD: Может проще тогда сделать не const CharT[&lit][N + 1], а CharT lit[N + 1]. Проще использовать, но вроде как произойдет копирование, а не сохранение исходных символов? (Просто хотелка)

Answer 1

Непонятно, чем вам ::std::string_view не угодил:

#include <iostream>
#include <string_view>
constexpr ::std::string_view const lit1{"Literal1"};
constexpr auto const psz_literal{"Literal2"};
constexpr ::std::string_view const lit2{psz_literal};
int main()
{
    ::std::cout << lit1.data() << ::std::endl;
    ::std::cout << lit2.data() << ::std::endl;
    return 0;
}

online compiler

READ ALSO
Ошибка 6 в Overlapped WSARecv

Ошибка 6 в Overlapped WSARecv

Пишу новый сервер на IOCPВ потоке приёма новых подключений вызываю WSARecv (после успешного accept естественно)

153
Парсинг хэдэр файлов

Парсинг хэдэр файлов

Есть такая задача: пройтись по хэдэр файлу и записать в список все методы класса, определенные в хэдэре, при этом отделить чистые виртуальные,...

133
Зачем выделять память для переменных в стеке?

Зачем выделять память для переменных в стеке?

В теме еще разбираюсь плохо так что прошу строго не судить

174
Неправильный выбор конструктора

Неправильный выбор конструктора

Почему эта программа выводит doubledouble, я же явно указываю int?!

158