Есть ли способ сделать эту ссылку на специализацию шаблона?

Я пробовал следующую иерархию, и она не связана. Вызов c->Execute() не виден, так как кажется, что он замаскирован Execute в Derived и не находит подходящего типа для использования. Я бы подумал, что если бы была проблема, она должна была бы проявиться при компиляции. Я пробовал с GCC 4.8 онлайн и с компилятором borland в Windows. Сообщение об ошибке одинаково в обоих случаях. Что-то в порядке:

/tmp/ccrT5mNy.o:(.rodata._ZTV7DerivedI5TypeCE[_ZTV7DerivedI5TypeCE]+0x10): undefined reference to `Derived<TypeC>::Execute()'
collect2: error: ld returned 1 exit status

Буду очень признателен за любые указатели.

#include <iostream>

class BaseType 
{
public: 
    BaseType() {}
    virtual void Execute() { std::cout << "BaseType execute..." << std::endl; };

protected:
};

struct TypeA;
struct TypeB;
struct TypeC;

class Derived2 : public BaseType
{
public:
    Derived2() : BaseType() {}
    virtual void Execute() { std::cout << "Derived execute2" << std::endl; }

protected:
};


template <typename T>
class Derived : public BaseType
{
public:
    Derived() : BaseType() {}
    virtual void Execute();

protected:
};

template <typename T>
class GrandChild : public Derived<T>
{
public:
    GrandChild() : Derived<T>() {}
    void Execute();
};

template<>
void Derived<TypeA>::Execute() { std::cout << "Derived execute... TypeA" << std::endl; }
template<>
void Derived<TypeB>::Execute() { std::cout << "Derived execute... TypeB" << std::endl; }
template<>
void GrandChild<TypeC>::Execute() { std::cout << "Derived execute... TypeC" << std::endl; }


int main()
{
    BaseType* a = new Derived<TypeA>();      
    BaseType* b = new Derived<TypeB>();      
    BaseType* c = new GrandChild<TypeC>();      
    BaseType* d2 = new Derived2();
    a->Execute();
    b->Execute();
    c->Execute();
    d2->Execute();

    delete a;
    delete b;
    delete c;
    delete d2;
}

person Some Dude    schedule 05.12.2014    source источник


Ответы (1)


Derived<TypeC>::Execute() должен быть определен, даже если вы никогда его не вызываете, поскольку вы создаете экземпляр шаблона класса. Попробуйте добавить пустое определение или такое, которое throws и т. д., и программа должна связать и работать так, как вы ожидаете.

person aschepler    schedule 05.12.2014
comment
Это, безусловно, работает, если добавить специализацию, которую вы предлагаете. Большое спасибо за ответ. - person Some Dude; 09.12.2014