我偶然发现的原始问题是选择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
的类型和未具有skp
的类型都会调用它。
它编译(在gcc4.7上),但我不明白为什么:当enable_if
存在时,skipper_type
中的表达式应该评估为真(unused_type
是显然不等于{{1}}那么,并且调用应该是模棱两可的。我错在哪里?
答案 0 :(得分:1)
这里的问题是,正如评论中所总结的那样,当仅使用U::skp
时,可能是U
被推断为引用类型(即,当传递左值解析器时)。当发生这种情况时,你会得到SFINAE,因为参考类型显然没有嵌套任何。
此修复方法是使用U
删除std::remove_reference
的引用,以便您拥有(sizeof(std::remove_reference<T>::type::skp) != 0)
。请注意,此处不需要typename
,因为::skp
表示type
必须是类型名称。