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_ifs 中的表达式都应该评估为真(skipper_type显然不等于unused_typethen),并且调用应该是模棱两可的。我错在哪里?

4

1 回答 1

1

正如评论中所得出的结论,这里的问题是,当使用 just 时U::skp,可能会U被推断为引用类型(即,当传递左值解析器时)。发生这种情况时,您将启动 SFINAE,因为引用类型显然没有嵌套任何东西

解决方法是从Uwith中删除引用,std::remove_reference以便您拥有(sizeof(std::remove_reference<T>::type::skp) != 0). 请注意,typename此处不需要,因为::skp表示type必须是类型名。

于 2012-10-25T00:42:09.003 回答