У меня проблема с g ++ и с тем, как шаблоны взаимодействуют с указателями на функции. Рассмотрим следующее объявление шаблона.
template <class T,class B> class TestTemplate {
private:
T* context;
public:
TestTemplate(T* usingClass);
B* testfcnOK(B* arg);
B* testfcnBAD(B* (T::*fcn)(void));
};
template <class T,class B> TestTemplate<T,B>::TestTemplate(T* usingClass) {
context = usingClass;
}
template <class T,class B> B* TestTemplate<T,B>::testfcnOK(B* arg) {
return arg;
}
template <class T,class B> B* TestTemplate<T,B>::testfcnBAD(B* (T::*fcn)(void)) {
return (context->*fcn)();
}
Думайте о T как о классе, который содержит различные функции, которые возвращают объекты типа B. Метод, на котором следует сосредоточиться выше, это testfcnBAD (), поскольку он вызывает проблему. Вот код, который использует этот шаблон.
class Base { };
class Derived : public Base { };
class Tester {
public:
TestTemplate<Tester,Base> *templateClass;
Base* returnBase() { return new Base(); }
Base* returnDerivedOK() { return new Derived(); }
Derived* returnDerivedBAD() { return new Derived(); }
void runTest()
{
templateClass = new TestTemplate<Tester,Base>(this);
// These work.
Base* baseResult = templateClass->testfcnOK(new Base());
baseResult = templateClass->testfcnOK(new Derived());
baseResult = templateClass->testfcnBAD(&Tester::returnBase);
Derived* derivedResult = (Derived*) templateClass->testfcnBAD(&Tester::returnDerivedOK);
// This does not work.
derivedResult = (Derived*) templateClass->testfcnBAD(&Tester::returnDerivedBAD);
}
};
Когда задана последняя строка runTest (), g ++ (4.5.2) задыхается. Кажется, проблема в том, что testfcnBAD () передается указатель на функцию, которая возвращает экземпляр Derived, а TestTemplate объявляет testfcnBAD () для получения указателя на функцию, которая возвращает базовый объект. Кажется, что этот код должен быть в порядке, потому что производный объект является базовым объектом, но тот факт, что Derived является подклассом Base, может быть потерян где-то вдоль линии.
Я что-то здесь упускаю, и есть ли обходной путь?