我正在尝试为一个类的用户(下面的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 ++还不支持它们。还有什么其他的吗?非常感谢!
答案 0 :(得分: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
与我的其他答案一样。我会留下那个作为巴洛克式愚蠢的例子。