我正在通过编写C ++ lambdas来实现parser combinators。
例如:
// rule_character.cpp
#include "rule_character.hpp"
LexerRule character_name =
(make_terminal("alarm") & replace_with("\a")
| (make_terminal("backspace") & replace_with("\b"))
| (make_terminal("delete") & replace_with("\x7f"))
| (make_terminal("escape") & replace_with("\x1b"))
| (make_terminal("newline") & replace_with("\n"))
| (make_terminal("null") & replace_with("\0"))
| (make_terminal("return") & replace_with("\r"))
| (make_terminal("space") & replace_with(" "))
| (make_terminal("tab") & replace_with("\t"))) / "character-name";
LexerRule character =
((make_terminal("#\\") & ignore_string) +
(character_name
| ((make_terminal("x") & ignore_string)
+ (hex_scalar_value & replace_hex_scalar_value))
| (make_class([](char c) { return true; }, "any-character"))))
/ "character";
其中LexerRule
是std::function
类型的别名。
以下是标题:
// rule_character.hpp
extern LexerRule character_name;
extern LexerRule character;
然而,在main.cpp
中,正在抛出std::bad_function_call
:
// main.cpp
// When: you try to parse a series of identifier
skip_ws(lex);
// When: you try to parse a string
std::cout << (void*)(rules::character.target<LexResult (*) (LexerInput&)>() )
<< std::endl;
LexResult result = rules::character(lex);
while (result.is_token()) {
results.push_back(result);
skip_ws(lex);
result = rules::character(lex);
}
但target
为0
或nullptr
。即使我确定两个.cpp
源文件'各自的.o
目标文件被链接,为什么会这样呢?为什么我的全球lambda没有初始化?
答案 0 :(得分:3)
问题与static initialization order有关。由于lambda通常依赖于彼此已经按特定顺序初始化,因此初始化不会发生,并且全局lambda将保持无效状态,从而在运行时导致Consumer
异常。
为了解决这个问题,我将全局lambda变量的初始化移动到了运行时。