У меня есть несколько запросов SQL с привязками в моем коде C ++, эти запросы static const std::string
Поскольку эти запросы сложны, очень легко ошибиться с некоторыми деталями. Я хотел бы сделать некоторые очень простые проверки во время компиляции, например, подсчет количества запятых или :
персонаж.
Ты не можешь static const std::string
не существует во время компиляции.
Строковые литералы возможны с constexpr
функции, но не std::string
объекты.
std::string
не существует во время компиляции. Если вы хотите иметь такое поведение, вы можете использовать строковые литералы с constexpr, как показано ниже:
constexpr const char* const var = "string";
Чтобы узнать больше об этом, пожалуйста, смотрите код сборки, сгенерированный для этого:
#include <string>
int main()
{
constexpr const char* const str = "string";
const std::string test = "test";
}
С X86-64 Clang 6.0.0
компилятор и с 0
оптимизаций,
constexpr const char* const str = "string";
сгенерированный ниже код:
subq $80, %rsp
movq $.L.str, -8(%rbp)
leaq -48(%rbp), %rax
.L.str:
.asciz "string"
и для const std::string test = "test";
код ниже генерируется (просто фрагмент)
Так он называет std::allocater
который выделяет память в куче, а затем создает строковый объект.
movq %rax, %rdi
movq %rax, -72(%rbp) # 8-byte Spill
callq std::allocator<char>::allocator() [complete object constructor]
movl $.L.str.1, %ecx
movl %ecx, %esi
leaq -40(%rbp), %rdi
movq -72(%rbp), %rdx # 8-byte Reload
callq std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
jmp .LBB0_1
Вы не можете разобрать std::string
во время компиляции, потому что он может быть создан только во время выполнения. Но в StackOverflow есть хорошие ответы, которые описывают, как определять и обрабатывать строки во время компиляции:
Они относятся к Скотт Шурр str_const начиная со страницы 29:
class str_const { // constexpr string
private:
const char* const p_;
const std::size_t sz_;
public:
template<std::size_t N>
constexpr str_const(const char(&a)[N]) : // ctor
p_(a), sz_(N-1) {}
constexpr char operator[](std::size_t n) { // []
return n < sz_ ? p_[n] : throw std::out_of_range("");
}
constexpr std::size_t size() { return sz_; } // size()
};
Смотри как Contexpr JSON парсер JSON работает. Он способен анализировать всю строку JSON во время компиляции, поэтому должна быть возможность анализировать и проверять SQL во время компиляции. Для этого вам просто нужно использовать std_const Скотта или static_string Джейсона.
Вот тривиальное расширение, которое заставляет его играть лучше std::string_view
и иметь время компиляции substr
метод:
class str_const {
private:
const char* const p_;
const std::size_t sz_;
public:
template<std::size_t N>
constexpr str_const(const char(&a)[N]) :
p_(a), sz_(N-1) {}
constexpr str_const(const std::string_view & sv) :
p_(sv.begin()), sz_(sv.size()) {}
constexpr operator std::string_view() const
{ return {p_, sz_}; }
constexpr char operator[](std::size_t n) const { // []
return n < sz_ ? p_[n] : throw std::out_of_range("");
}
constexpr std::size_t size() const { return sz_; } // size()
constexpr const char*c_str() const { return p_; }
constexpr const char*begin() const { return p_; }
constexpr const char*end() const { return p_ + sz_; }
constexpr str_const substr(unsigned from, unsigned size) const
{
return from+size <= sz_ ? std::string_view{p_ + from, size} : throw std::out_of_range("");
}
};
std::ostream & operator<<(std::ostream& out, str_const str) {
return out << std::string_view(str);
}
Как уже говорил Себастьян, вы не можете, если вам нужно std::string
, Но, возможно, в качестве альтернативы, вы можете сделать что-то вроде constexpr auto query = "MY SQL QUERY";
Я не знаю, разрешено ли вам изменять тип запросов.
Затем во время выполнения, query
может быть использован для построения std::string
если вам нужно. Проверки во время компиляции также могут быть сделаны.
Недостатком, конечно, является то, что он копируется во время выполнения при создании std :: string.