2010-08-17 57 views
3

調用我試圖提供從可變參數層次得出一個簡單而整潔的方式來明確地調用成員函數,它接受一個類的用戶(以下MyGizmo)(以下ObjGetter)沒有參數(下面的檢查())。我可以使用帶參數的函數(如下面的tune())進行這項工作,但是我還沒有找到一種方法使它對不帶參數的函數有效。消歧參數,功能較少的可變參數的類層次

struct Base { }; 
struct ObjA : public Base { }; 
struct ObjB : public Base { }; 
struct ObjC : public Base { }; 

template <class ... Obj> struct ObjGetter; 

template <class Obj, class ... Tail> 
struct ObjGetter<Obj, Tail ...> : public ObjGetter<Tail ...> 
{ 
    using ObjGetter<Tail ...>::tune; // resolve ambiguous lookups for tune() 

    void tune(Obj * obj) { } // no problem with this one, disambiguated by obj type 

    Obj * check() const { return 0; } // problem with this one, no arg to disambiguate 
}; 

template <> struct ObjGetter<> { // to terminate the recursion 
    void tune(void); // needed by the using statement above but should not be used, hence different syntax 
}; 

struct MyGizmo : public ObjGetter<ObjA, ObjC> // variadic 
{ 
    void testit() { 
    ObjA * a = 0; ObjB *b = 0; ObjC *c = 0; 

    a = ObjGetter<ObjA, ObjC>::check(); // too ugly! 
    c = ObjGetter<ObjC>::check(); // too ugly! 

    tune(a); // no problem 
    //tune(b); // correct compile-time error: no matching function for call to ‘MyGizmo::tune(ObjB*&)’ 
    tune(c); // no problem 

    // I would like a simple syntax like this: 
    //a = check<ObjA>(); // should call ObjGetter<ObjA, ObjC>::check() 
    //b = check<ObjB>(); // should give a compile-time error 
    //c = check<ObjC>(); // should call ObjGetter<ObjC>::check() 
    } 
}; 

我曾嘗試以下,但我不能完全satistified:

首先,我可以使用獲取層級隨身攜帶的輔助,只需-模板類,減少醜陋的調用只有一個模板arg;產生這樣的:

a = ObjGetterHelper<ObjA>::check(); // still ugly! MyGizmo user should not have to know about ObjGetterCore 
c = ObjGetterHelper<ObjC>::check(); // too ugly! 

我可以用一個Type2Type幫手,給檢查()的說法,這工作得很好,看起來是這樣的:

a = check(Type2Type<ObjA>()); // pretty ugly too 
c = check(Type2Type<ObjC>()); // pretty ugly too 

我可以用宏,但我不希望去那裏......

#define CHECK(X) check(Type2Type<X>()) 

我認爲,模板別名將提供一個解決方案,但我使用G ++不支持他們呢。在此期間還有其他事情嗎?非常感謝!

+0

'check'做什麼?我理解這個問題,但是當我不知道如何處理「check」時,很難給出正確的答案。 (他們都返回0;'?值從哪裏來?) – GManNickG 2010-08-17 20:27:31

+0

check()實際上輪詢Blackboard是否有某個Object已經發布到它並且可用。在完整的實現中,它將shared_ptr返回給發佈的Object(如果存在)或null shared_ptr。 – 2010-08-18 00:26:51

回答

2

如果類型與可變參數列表的頭部不匹配,您需要一個具有某種結構的成員函數模板check<Type>來委託繼承鏈。

這是SFINAE的一個經典問題。

template< class Obj2 > 
    typename std::enable_if< std::is_same< Obj, Obj2 >::value, Obj * >::type 
    check() const { return 0; } // perform work 

    template< class Obj2 > 
    typename std::enable_if< ! std::is_same< Obj, Obj2 >::value, Obj2 * >::type 
    check() const { return base::template check<Obj2>(); } // delegate 

與我的其他答案相同。我會留下那個作爲巴洛克式愚蠢的例子。

+0

是的,這是美麗的,非常感謝,偉大的東西! – 2010-08-18 00:24:09