The original problem I tried to solve when stumbled upon this was to select parse_impl
version:
U
) provides a field named "skp"
, use that field;I came up with the following code:
// 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);
}
The call site look like this:
pr.is_ok = parse_impl(pr.position, input.cend(), parser, pr.attr);
and this is called both for types having skp
and ones that haven't.
And it compiles (on gcc4.7), but I don't understand why: when skp
is present, expressions in both enable_if
s should evaluate to true (skipper_type
is obviously not equal to unused_type
then), and the call should be ambiguous. Where am I mistaken?
The problem here is, as concluded in the comments, that when using just U::skp
, it might be that U
is deduced as a reference type (i.e., when passing an lvalue parser). When this happens, you get SFINAE going, as a reference type obviously has no nested anything.
The fix is to remove the reference from U
with std::remove_reference
so that you have (sizeof(std::remove_reference<T>::type::skp) != 0)
. Note that typename
is not needed here, since ::skp
indicates that type
has to be a typename.