C++ 使用模板实现通用字符串解析器
我正在尝试提出一种解析字符串(使用给定格式)的通用解决方案。例如,我希望能够解析包含数值列表(整数或浮点数)的字符串并返回std::vector。这就是我到目前为止所做的:C++ 使用模板实现通用字符串解析器,c++,parsing,templates,c++11,C++,Parsing,Templates,C++11,我正在尝试提出一种解析字符串(使用给定格式)的通用解决方案。例如,我希望能够解析包含数值列表(整数或浮点数)的字符串并返回std::vector。这就是我到目前为止所做的: template<typename T, typename U> T parse_value(const U& u) { throw std::runtime_error("no parser available"); } template<typename T> std::vect
template<typename T, typename U>
T parse_value(const U& u) {
throw std::runtime_error("no parser available");
}
template<typename T>
std::vector<T> parse_value(const std::string& s) {
std::vector<std::string> parts;
boost::split(parts, s, boost::is_any_of(","));
std::vector<T> res;
std::transform(parts.begin(), parts.end(), std::back_inserter(res),
[](const std::string& s) { return boost::lexical_cast<T>(s); });
return res;
}
到目前为止,我当前的解决方案不起作用(编译器无法推导出要使用的确切函数)。我想问题在于我的解决方案依赖于根据
parse_value
函数的返回类型推断模板值。我真的不知道如何解决这个问题(甚至不知道是否有可能解决它,因为设计方法可能完全有缺陷)。有人知道解决我要做的事情的方法吗?如果您能为我指出一种可能的方法来解决我当前实施中遇到的问题,我将不胜感激。顺便说一句,对于解决这个问题,我肯定也会有完全不同的想法。您不能基于返回值[1]重载函数。这正是标准IO库使用以下结构的原因:
std::cin >> a >> b;
这可能不是小菜一碟——许多人不喜欢它,而且它也确实存在问题——但它在为解析器提供目标类型方面做得很好。与静态parse(const std::string&)
原型相比,它还有一个优势,即它允许链接和流式处理,如上所述。有时这是不需要的,但在许多解析上下文中它是必不可少的,而操作符>>
的使用实际上是一种非常酷的语法。[2]
标准库没有做最酷的事情,那就是跳过字符串常量scanf
样式并允许交叉读取
vector<int> integers;
std::cin >> "[" >> interleave(integers, ",") >> "]";
向量整数;
std::cin>>“[”>>交织(整数),”>>“]”;
然而,这是可以定义的。(可能最好在字符串文本周围使用显式包装器,但实际上我更喜欢这样;但是如果要传递变量,则需要使用包装器)
[1] 有了新的
auto
声明,这样做的原因就更加清楚了
[2] 另一方面,IO操纵者是一个残酷的笑话。错误处理是可怜的。但是你不可能拥有所有的东西。这里有一个libsass解析器的例子:
const char* interpolant(const char* src) {
return recursive_scopes< exactly<hash_lbrace>, exactly<rbrace> >(src);
}
// Match a single character literal.
// Regex equivalent: /(?:x)/
template <char chr>
const char* exactly(const char* src) {
return *src == chr ? src + 1 : 0;
}
const char*interplant(const char*src){
返回递归的_范围<精确地,精确地>(src);
}
//匹配单个字符的文字。
//正则表达式等价物:/(?:x)/
模板
常量字符*精确(常量字符*src){
return*src==chr?src+1:0;
}
其中可以将规则传递到lex方法。调用
parse_value
类型,即parse_value(str)
@Nim,当我直接调用parse_value
解析整数向量时,该类型起作用。但我不能从解析\u可选\u值
中执行此操作。至少我看不出…你为什么要避开现有的解析器库,例如?@ildjarn我现在正在查看它们。谢谢你的链接!
vector<int> integers;
std::cin >> "[" >> interleave(integers, ",") >> "]";
const char* interpolant(const char* src) {
return recursive_scopes< exactly<hash_lbrace>, exactly<rbrace> >(src);
}
// Match a single character literal.
// Regex equivalent: /(?:x)/
template <char chr>
const char* exactly(const char* src) {
return *src == chr ? src + 1 : 0;
}