Я пытаюсь предоставить пользователям класса (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()
}
};
Я пробовал следующее, но не полностью удовлетворен:
Сначала я могу использовать вторичный, просто шаблонный класс, который переносится в иерархии, чтобы уменьшить уродливый вызов, чтобы иметь только один аргумент шаблона; дает что-то вроде:
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 ++, который их пока не поддерживает. Есть ли что-нибудь еще в это время? Большое спасибо!