Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.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++_Parsing_Templates_C++11 - Fatal编程技术网

C++ 使用模板实现通用字符串解析器

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

我正在尝试提出一种解析字符串(使用给定格式)的通用解决方案。例如,我希望能够解析包含数值列表(整数或浮点数)的字符串并返回std::vector。这就是我到目前为止所做的:

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;
}