Dariusz
Dariusz

Reputation: 610

no suitable definition provided for explicit template instantiation request

I have a Calculator<T> class and a LoggingCalculator<T> class, which inherites from Calculator<T>. Calculator<T> has a virtual methods like add, multiply etc. In a child class LoggingCalculator<T> I am trying to override these methods. I have already overrided the add method, fine. But I cannot override multiply, because compiler says:

Calculator::Calculator[int]::Calculator(void)': no suitable definition provided for explicit template instantiation request

even though, I explicitly instantiated my templates. I really do not understand, why this error occures with overriding multiply method, while add compiles fine.

The really weird thing is that it does compile, if I do not return generic value returned from base class method. But If want to return result from the base class method, it does not compile. See LoggingCalculator.cpp code below.

Calculator.h:

template <class T>
class Calculator
{
public:
    Calculator();
    ~Calculator();
    virtual T add(T a, T b);
    virtual T multiply(T a, T b);
}
template class Calculator<int>;
template class Calculator<long>;
template class Calculator<float>;
template class Calculator<double>;

Calculator.cpp:

template<class T>
Calculator<T>::Calculator() {}

template<class T>
Calculator<T>::~Calculator() {}

template<class T>
T Calculator<T>::add(T a, T b)
{
    return a + b;
}

template<class T>
T Calculator<T>::multiply(T a, T b)
{
    return a * b;
}

LoggingCalculator.h:

template <class T>
class LoggingCalculator : public Calculator<T>
{
public:
    LoggingCalculator();
    ~LoggingCalculator();
    T add(T a, T b) override;
    T multiply(T a, T b) override;
};

template class LoggingCalculator<int>;
template class LoggingCalculator<long>;
template class LoggingCalculator<float>;
template class LoggingCalculator<double>;

LoggingCalculator.cpp:

template<class T>
LoggingCalculator<T>::LoggingCalculator() { }

template<class T>
LoggingCalculator<T>::~LoggingCalculator() {}

template<class T>
T LoggingCalculator<T>::add(T a, T b)
{
    T result = Calculator<T>::add(a, b);
    return result;
}

template<class T>
T LoggingCalculator<T>::multiply(T a, T b)
{
    T result =  Calculator<T>::multiply(a, b);
    //return a * b; // COMPILES FINE!
    return result // CAUSES ERROR
}

Upvotes: 2

Views: 1662

Answers (1)

You'll have to move the explicit instantiations to their respective source files. That's because definitions of what you're instantiating need to be accessible at the point of instantiation.

What you're doing now instantiates the definition of the class Calculator<int> and with it, the declaration of Calculator<int>::add, but it does not instantiate the definition of Calculator<int>::add, because the definition is not available.

And since explicit template instantation is a definition, it should normally not appear in a header file anyway — that would likely lead to multiple-definition issues down the line.

Upvotes: 3

Related Questions