2
我想,当在此跌跌撞撞,解决了原来的问题是选择parse_impl
版本:看似暧昧的模板函数重载
- 如果(
U
型)解析器提供了一个名为"skp"
场,使用该字段; - 如果不是,请使用默认值。
我想出了下面的代码:
// This variant compiles for parsers requiring a skipper:
template <typename I, typename U, typename A,
typename = typename std::enable_if<
not std::is_same<
typename std::remove_reference<U>::type::skipper_type,
qi::unused_type
>::value
>::type,
typename = void > // avoid redefinition (1 more overload not shown)
bool parse_impl(I & start, I end, U && parser, A & attr)
{
// qi::space by default:
return qi::phrase_parse(start, end, parser, qi::space, attr);
}
// This variant compiles for parsers providing skipper via 'skp' member:
template <typename I, typename U, typename A,
typename = typename std::enable_if<
not std::is_same<
typename std::remove_reference<U>::type::skipper_type,
qi::unused_type
>::value
&& (sizeof(U::skp) != 0)
>::type,
typename = void, typename = void > // avoid redefinition
bool parse_impl(I & start, I end, U && parser, A & attr)
{
// parser.skp is available:
return qi::phrase_parse(start, end, parser, parser.skp, attr);
}
调用点是这样的:
pr.is_ok = parse_impl(pr.position, input.cend(), parser, pr.attr);
,这被称为既具有skp
和那些没有类型。
并将其编译(上gcc4.7),但我不明白为什么:当skp
存在,在这两个enable_if
表示方法应该评估为真(skipper_type
显然不等于unused_type
的话),以及呼叫应该是含糊不清的。我错在哪里?
[减少的测试用例](http://liveworkspace.org/code/5a6093ff1c940b48071231ec1d1d12bf)至少是不明确的,我看不出我在那里做了什么不同。我只能猜测你的第三个重载,即带有'skp'的重载,实际上从某种程度上来说并不会被调用,如果这确实为你编译的话。也许把一些测试打印语句放在里面?最后,我建议阅读[本博客文章](http://rmartinho.github.com/2012/06/01/almost-static-if.html)以及[this](http://stackoverflow.com/q/12654067/500104)问题和[this](http://stackoverflow.com/a/9154394/500104)的答案。 :) – Xeo
@Xeo:我终于钉上了它。实际上有一个区别:'代码中的sizeof(NoRef :: skp)'和'(sizeof(U :: skp)!= 0)'在我的。 'NoRef'终于带来了歧义! *巨大*感谢您的帮助和链接! –
vines
啊,所以你的问题是,当你通过一个左值(并且“U”被推断为一个参考)时,你会得到你的SFINAE。 :)事实上,[这是问题](http://liveworkspace.org/code/f35132f82751e262fd6a64515e11bebd)。 – Xeo