如何在编译时解析静态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);
    }