Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;17 constexpr字符串解析_C++_Parsing_C++17_Constexpr - Fatal编程技术网

C++ C++;17 constexpr字符串解析

C++ C++;17 constexpr字符串解析,c++,parsing,c++17,constexpr,C++,Parsing,C++17,Constexpr,很抱歉,这将是一篇很长的文章,但我觉得您需要所有的代码来查看发生了什么 所以,我一直在试验编译时字符串到数据结构解析器的想法。想象一下regex,其中字符串在编译时“编译”到数据结构中,但在运行时执行(当然,只要输入字符串是常量)。但我遇到了一个问题,我不太明白到底出了什么问题: 基本上,我的设计是一个2遍的解析器: 第1步:确定输入字符串中有多少“操作码” 过程2:返回一个数组,其大小由过程1决定,并用“操作码”填充 事情是这样的: // a class to wrap string c

很抱歉,这将是一篇很长的文章,但我觉得您需要所有的代码来查看发生了什么


所以,我一直在试验编译时字符串到数据结构解析器的想法。想象一下regex,其中字符串在编译时“编译”到数据结构中,但在运行时执行(当然,只要输入字符串是常量)。但我遇到了一个问题,我不太明白到底出了什么问题:

基本上,我的设计是一个2遍的解析器:

  • 第1步:确定输入字符串中有多少“操作码”
  • 过程2:返回一个数组,其大小由过程1决定,并用“操作码”填充
事情是这样的:

// a class to wrap string constants
class constexpr_string {
public:
    template <size_t N>
    constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1) {}
public:
    constexpr size_t size() const     { return size_; }
    constexpr size_t capacity() const { return size(); }
    constexpr size_t empty() const    { return size() != 0; }
public:
    constexpr char operator[](size_t n) const { return string_[n]; }
private:
    const char *string_;
    size_t      size_;
};

// would have loved to use std::array, but ran into an issue so..
// wrapped in a struct so we can return it
template <class T, size_t N>
struct constexpr_array {
    T array[N] = {};
};

struct opcode { /* not relevant */ };

template <size_t N>
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
    constexpr_array<opcode, N> compiled;
    /* fill in compiled_format */
    return compiled;
}

constexpr size_t calculate_size(constexpr_string fmt) {
    size_t size = 0;
    /* calculate size */
    return size;
}

#if 0
// NOTE: Why doesn't **This** work?
constexpr int test(constexpr_string input) {

    constexpr size_t compiled_size = calculate_size(input);
    constexpr auto compiled_format = compile_string<compiled_size>(input);
    return 0;
}
#endif

int main() {
    // NOTE: when this works...
    constexpr char input[] = "...";
    constexpr size_t compiled_size = calculate_size(input);
    constexpr auto compiled = compile_string<compiled_size>(input);
    execute(compiled); // run it!
}
让我们减少这一点:

constexpr void f(int i) {
    constexpr int j = i; // error
}

int main() {
    constexpr int i = 0;
    constexpr int j = i; // OK
}

函数参数从来不是
constexpr
,因此
i
f
中不是一个常量表达式,不能用于初始化
j
。一旦你通过一个函数参数传递了一些东西,constexpr属性就丢失了。

这听起来确实是正确的:-/当然,我读过一些关于人们使用
constexpr
进行编译时解析的巧妙技巧的文章,人们正在做些什么来解决这个问题?一般的解决方法是将值放入模板非类型参数(或其包)中。对于字符串文字来说,这尤其困难,AFAIK在C++20之前需要一个非标准的扩展(仅由GCC和Clang支持)。好的,我认为您的答案基本上是正确的。。。但是您的简化代码不太具有代表性。我现在正在看一些对我来说毫无意义的东西:这是有效的:constexpr size_t Func(constexpr_字符串输入){if(输入[0]='X'){return 1;}return 0;}这不是:constexpr size_t Func(constexpr_字符串输入){constexpr char ch=input[0];if(ch='X'){return 1;}返回0;}
constexpr size\u t编译的大小=计算大小(输入)
是有效的,因为
input
在这里是constexpr,而
calculate\u size(input)
作为一个整体,是一个有效的常量表达式。在
calculate_size
内部,它的参数不是constexpr,但这并不能阻止整个函数调用表达式成为constexpr。@t.C.关于“一般的解决方法是将值放入模板非类型参数中”——您不能使用类似
constexpr
lambda的
[]constexpr{return string“sv;}
?由于这个问题是用c++17标记的,您是否考虑过在实现中使用
std::string\u view
std::string_视图
的构建考虑了
constexpr
,因此它绝对值得一看@当然是Hugotexeira。我的计划是,一旦我掌握了我所尝试的以我想要的方式工作的核心概念,就切换到string_视图。你有什么理由必须使用string吗?使用操作符或对象表示正则表达式规则(例如kleene星)可能会容易得多。我相信Boost.Spirit就是这么做的。“regex”是用来比喻我想做的事情的。如:字符串->状态->执行状态。我希望有一个很好的方法在编译时完成第一部分。。。看起来这样做有点复杂。你可能会对Ben Deane和Jason Turner的实验性
constexpr
JSON解析器感兴趣。他们的实验题为“康斯特普勒一切”。在()和()举行了会谈。是的,但是我建议你看演讲。
constexpr void f(int i) {
    constexpr int j = i; // error
}

int main() {
    constexpr int i = 0;
    constexpr int j = i; // OK
}