I have some SQL queries with binds in my C++ code, those queries are static const std::string
, because those queries are complex it is very easy to be wrong with some details. I would like to do some very basic checks in compilation time, for example counting the number of commas or :
character.
You can't. A static const std::string
doesn't exist at compile time.
String literals are possible with constexpr
functions, but not std::string
objects.
You can't parse std::string
at compile time, because it can be constructed only at run-time. But there are nice answers at StackOverflow that describes how to define and manipulate compile-time strings:
They refer to of Scott Schurr's str_const starting at page 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()
};
See how Jason Turner's constexpr JSON parser works. It is able to parse a whole JSON string at compile time, so it should be possible to parse and validate SQL at compile time. You just need to use Scott's std_const, or Jason's static_string for that.
Here is a trivial extension that makes it play nicer with std::string_view
, and have a compile-time substr
method:
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With