Specialize a method form base class in a derived template class


Keywords:c++ 


Question: 

I am having a bad time figuring out how should I make a template specialization. This time, unfortunately, google and SO couldn't help me.

For the base class:

class base
{
public:
    virtual ~base() = 0;

    virtual int getInt() { throw std::invalid_argument(std::string(typeid(*this).name()) + " can't return int"); }
};
base::~base() {}

and derived class:

template<class T>
class derived : public base
{
public:
    derived() {}
    derived(T value) { mValue = value; }

private:
    T mValue;
};

This code:

void proof(base* arg)
{
    try
    {
        std::cout << arg->getInt();
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
    }
    std::cout << "\n\n";
}

int main()
{
    base* a = new derived<int>(23);
    base* b = new derived<std::string>("abc");

    proof(a);
    proof(b);

    delete a;
    delete b;

    return 0;
}

output, if wasn't already obvious:

class derived<int> can't return int

class derived<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > can't return int

How should I make a specialization of derived so getInt() would return the mValue ? Something like:

template<>
int derived<int>::getInt() { return mValue; } 

This is not working.

To be more clear, I expect to pe output 23, when I call arg->getInt() and the exception I throw in base class when I call arg->getInt(). Can you give me a sample code ? Thank you.


2 Answers: 

The derived template does not have a getInt() method. You can't specialize what does not exist.

You have to specialize the entire template. Try this:

template<>
class derived<int> : public base
{
public:
    derived() {}
    derived(int value) { mValue = value; }
    int getInt() override { return mValue; } 
private:
    T mValue;
};


You could specialize the template for int:

template <> class derived<int> : public base
{
public:
    derived(int value) : mValue(value) {}

    int getInt() override { return mValue; }

private:
    int mValue;
};