我有一個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