我有一个sfinae类,它测试一个类是否是解析器规则(AX解析器生成器库)。 如果P满足解析器规则要求,axe::is_rule<P>::value
应评估为true。解析器规则必须具有以下部件的功能之一,以一对迭代器和返回axe::result<Iterator>
:如何编写SFINAE来测试解析器规则?
template<class Iterator>
axe::result<Iterator> P::operator()(Iterator, Iterator);
,或者它的专业化,或者非模板对于某些类型的图表
axe::result<CharT*> P::operator()(CharT*, CharT*);
,或const以上版本。理论上,可以有一个以上的超载operator()
,尽管实际上对于具有上述签名之一的单个operator()
的测试就足够了。
不幸的是,is_rule
目前的实施只处理一些情况,但不是全部情况。有一些不幸的类,该失败is_rule
测试:
#define AXE_ASSERT_RULE(T)\
static_assert(axe::is_rule<typename std::remove_reference<T>::type>::value, \
"type '" #T "' is not a rule");
例如,以下不幸类型测试失败:
struct unfortunate
{
axe::result<const unsigned char*>
operator()(const unsigned char*, const unsigned char*);
};
AXE_ASSERT_RULE(unfortunate);
// or same using lambda
auto unfortunate1 = [](const unsigned char*, const unsigned char*)
->axe::result<const unsigned char*> {};
AXE_ASSERT_RULE(decltype(unfortunate1));
typedef std::vector<char>::iterator vc_it;
struct unfortunate2 { axe::result<vc_it> operator()(vc_it, vc_it) const; };
AXE_ASSERT_RULE(unfortunate2);
typedef axe::result<const char*> (unfortunate3)(const char*, const char*);
AXE_ASSERT_RULE(unfortunate3);
struct rule { template<class I> axe::result<I> operator()(I, I); };
class unfortunate4 : public rule {};
AXE_ASSERT_RULE(unfortunate4);
在AX
当前的解决方案是包装那些在转发封套( class r_ref_t
),当然这会产生句法瑕疵(毕竟,解析器生成器都是关于语法糖的)。
如何修改is_rule
中的sfinae测试来涵盖上述不幸的情况?
不幸的是,'is_rule'类不能采用迭代器类型,因为没有办法指定它。当创建规则表达式时,迭代器类型是未知的,不能被指定。例如,(运算符&see http://tinyurl.com/3kmmcmh)表达式'auto rule = A & B;'是迭代器不可知的,规则A和B可以采取各种迭代器形式或者是复合规则本身,但是我必须能够为任何兼容的迭代器调用'rule(i1,i2)'。只要所有规则都实现了模板化的'operator()',我很好,否则(重要的是lambda函数)''is_rule'测试不幸失败。 – 2011-05-25 22:20:59
如果你想确定一个有限的迭代器集合,你可以修改上面的代码来检查任何有限的迭代器集合,如果规则适用于任何一组迭代器,则返回true。 – 2011-05-25 22:24:35
我明白你的意思了。它会严重夸大代码,每个复合规则(并且有很多)必须为每个参数测试所有可能迭代器的所有可能组合。像这样:'template r_and_t < typename std :: enable_if :: type,It1> :: value | is_rule :: type,It2> :: value, R1> :: type, typename std :: enable_if :: type,It1> :: value | is_rule :: type,It2> :: value, R2> :: type > operator&(R1 && r1,R2 && r2);'... –
2011-05-25 22:54:27