簡體   English   中英

在可變參數類層次結構中消除無參數函數調用的消歧

[英]Disambiguating argument-less function calls in variadic class hierarchies

我試圖提供一個類的用戶(下面的MyGizmo),它來自一個可變參數層次結構(下面的ObjGetter),它有一個簡單,整潔的方式來明確地調用不帶參數的成員函數(下面的check())。 我可以使用帶參數的函數(如下面的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()
  }
};

我嘗試了以下但是並不完全滿意:

首先,我可以使用一個二級的,簡單模板化的類,它在層次結構中被攜帶,以減少丑陋的調用只有一個模板arg; 產生如下:

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

我可以使用Type2Type幫助器並給check()一個參數,這很好,看起來像這樣:

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

我可以使用宏但我不想去那里......

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

我認為模板別名將提供一個解決方案,但我使用的g ++還不支持它們。 還有什么其他的嗎? 非常感謝!

如果類型與可變參數列表的頭部不匹配,則需要使用某種結構的成員函數模板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

與我的其他答案一樣。 我會留下那個作為巴洛克式愚蠢的例子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM