如何在编译时解析静态const std::string? 我在C++代码中有一些SQL绑定,这些查询是代码>静态const STD::String ,因为这些查询很复杂,很容易出错。我想在编译时做一些非常基本的检查,例如计算逗号的数量或:字符。
你不能。编译时不存在如何在编译时解析静态const std::string? 我在C++代码中有一些SQL绑定,这些查询是代码>静态const STD::String ,因为这些查询很复杂,很容易出错。我想在编译时做一些非常基本的检查,例如计算逗号的数量或:字符。,c++,string,parsing,compilation-time,C++,String,Parsing,Compilation Time,你不能。编译时不存在静态常量std::string 字符串文字可以通过constexpr函数实现,但不能通过std::String对象实现。std::String在编译时不存在。如果希望有这样的行为,可以将字符串文字与constexpr一起使用,如下所示: constexpr const char* const var = "string"; 要了解更多信息,请参阅为此生成的汇编代码: #include <string> int main() { constexpr co
静态常量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";
}
生成以下代码:
subq $80, %rsp
movq $.L.str, -8(%rbp)
leaq -48(%rbp), %rax
.L.str:
.asciz "string"
对于const std::string test=“test”代码>下面生成代码(只是一个片段)
因此它调用std::allocator
,它在堆上分配内存,然后构造string对象
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
movq%rax,%rdi
movq%rax,-72%(rbp)#8字节溢出
callq std::allocator::allocator()[完整对象构造函数]
movl$.L.str.1,%ecx
movl%ecx,%esi
leaq-40%(rbp),%rdi
movq-72(%rbp),%rdx#8字节重新加载
callq std::\uuucxx11::基本字符串::基本字符串(char const*,std::allocator const&)
jmp.LBB0_1
正如塞巴斯蒂安已经提到的,如果您需要std::string
,就不能这样做。但是,作为替代方案,您可以执行类似于constexpr auto query=“MY SQL query”的操作代码>我不知道是否允许您修改查询的类型。
然后在运行时,query
可以用来构造std::string
,如果需要的话。也可以在编译时进行检查
当然,缺点是在创建std::string时会在运行时复制它。您无法在编译时解析std::string
,因为它只能在运行时构造。但是StackOverflow中有一些很好的答案,描述了如何定义和操作编译时字符串:
它们指的是从第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()
};
您可以通过constexpr
函数和元编程基本实现这一点,而不是在编译时竭尽全力完成这一点(可能是因为您担心这些检查可能会对性能产生影响),我可以推荐两种常用的替代方案吗?1) 仅针对应用程序的调试版本有条件地编译这些检查(#ifndef NDEBUG…
)。您在开发过程中得到了检查,对发布性能没有任何影响。2) 测量,优化,测量。与SQL连接/查询相比,一些字符串检查很可能只需要很少的、可以忽略不计的时间。您甚至可能没有性能问题。@DevSolar我认为早期错误检查是在编译时解析的真正原因,而不是性能问题。OP实际上是这样说的:“我想在编译时做一些非常基本的检查”
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()
};
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);
}