C++17 constexpr 字符串解析

标签 c++ parsing c++17 constexpr

抱歉,这篇文章会很长,但我觉得你需要所有代码才能看到发生了什么。


所以,我一直在尝试将时间字符串编译为数据结构解析器的想法。想想像正则表达式这样的东西,其中字符串在编译时被“编译”成数据结构,但在运行时执行(当然只要输入字符串是常量)。但是我遇到了一个我不太明白出了什么问题的问题:

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

  • 第1关:确定输入字符串中有多少“操作码”
  • Pass 2:返回一个数组,其大小由Pass 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!
}

到目前为止一切顺利!

当我尝试将这两行包装成一个函数时,问题就出现了:-/。 我不明白为什么相同的代码在 main 中有效,但如果我只是尝试传递相同的代码 constexpr 对象到另一个函数,我开始收到关于不是 constexpr 的错误。


这是错误信息:

main.cpp: In function ‘constexpr int test(constexpr_string)’:
main.cpp:258:55: error: ‘input’ is not a constant expression
  constexpr size_t compiled_size = calculate_size(input);
                                                       ^
main.cpp:259:70: error: no matching function for call to ‘compile_string<compiled_size>(constexpr_string&)’
  constexpr auto compiled_format = compile_string<compiled_size>(input);
                                                                      ^
main.cpp:60:45: note: candidate: template<long unsigned int N> constexpr constexpr_array<opcode, N> compile_string(constexpr_string)
 constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
                                             ^~~~~~~~~~~~~~
main.cpp:60:45: note:   template argument deduction/substitution failed:

最佳答案

让我们减少这个:

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

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

函数参数永远不是constexpr,所以f里面的i不是常量表达式,不能用来初始化 j。一旦你通过函数参数传递一些东西,constexpr-ness 就会丢失。

关于C++17 constexpr 字符串解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51736678/

相关文章:

c++ - 基于迭代器构造boost优先级队列

c++ - CDC MFC 类成员函数 DPtoHIMETRIC() 功能在 Windows 7 和 Windows XP 之间会有所不同吗?

c++ - 如何在不使用指针的情况下编写对 10 个整数数组的引用?

c++ - 广度优先搜索修剪和内存泄漏 C++

java - 如何将长字符串在 "),"处分割成行?

xml - 使用自定义标签解析多个 XML 文件

java - Stanford Parser - 使用德语模型 jar

c++ - 允许对具有相同底层结构的类型进行隐式转换

c++ - 构造函数中的部分模板推导

c++ - 如何将任何化合物还原为非化合物类型