c++ - 消除可变类层次结构中无参数函数调用的歧义

标签 c++ templates c++11 variadic

我正在尝试为派生自可变层次结构(下面的 ObjGetter)的类(下面的 MyGizmo)的用户提供一种简单、整洁的方法来明确调用不带参数的成员函数(下面的 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>如果类型与可变参数列表的头部不匹配,则使用某种结构来委托(delegate)继承链。

这是 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

与我的其他答案一样。我将把那个作为巴洛克式愚蠢的一个例子。

关于c++ - 消除可变类层次结构中无参数函数调用的歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3506000/

相关文章:

c++ - 对于具有引用返回类型的搜索算法,默认返回值应该是什么?

c++ - 基于 std::function<> 的递归(?)函数包装器

找不到函数的 C++ 错误标识符?

使用函数的 C++ 字符串输入

c++ - 模板-模板参数给出神秘的类型/值不匹配

templates - Silverstripe - 是否可以在包含语句中使用变量?

c++ - 覆盖接口(interface)中的模板成员

c++ - C++中包含指令和前向声明之间的区别

c++ - 为什么 ChangeWindowMessageFilter 会导致 Qt 崩溃?

c++ - 我的编译器允许 "T&..."。这是一个扩展吗?