I am practicing function specialization, and I was trying to create a little storage object with a specialized print function. Here’s my code:
#ifndef STORAGE_HPP_
#define STORAGE_HPP_
#include <iostream>
using namespace std;
template <typename T, int size> class Storage
{ //LINE 16 ERROR
public:
Storage():arr(new T*[size]){};
~Storage()
{
for (int i = 0; i < size; i++)
{
delete arr[i];
}
delete[] arr;
}
void push(T obj, int i)
{
arr[i] = new T(obj);
}
void print()
{
for (int i = 0; i < size; i++)
{
cout << *arr[i];
}
cout << endl;
}
private:
T** arr;
};
template <typename T, int size> void Storage<int,size>::print() //LINE 38 ERROR
{
for (int i = 0; i < size; i++)
{
cout << (char) *arr[i];
}
cout << endl;
}
#endif /* STORAGE_HPP_ */
And I get this error:
../Storage.hpp:38:63: error: invalid use of incomplete type
class Storage<int, size>
../Storage.hpp:9:1: error: declaration of ‘class Storage<int, size>’
So, first question: can specialized functions be implemented inside a class? I tried but got an error.
Second, why do I get the error I’ve attached?
Thanks!
EDIT: I tried something new as someone here suggested. I’ve change print inside the class to be only void print() and I’ve implemented it outside so I can overload the function. Here:
template <typename T, int size>
void Storage<T,size>::print()
{
for (int i = 0; i < size; i++)
{
cout << *arr[i];
}
cout << endl;
}
template <typename T, int size>
void Storage<int,size>::print() //ERROR HERE
{
for (int i = 0; i < size; i++)
{
cout << *arr[i];
}
cout << endl;
}
Now I get invalid use of incomplete type ‘class Storage<int, size>’Where I wrote ERROR HERE (obviously!)
I understand that’s a common solution, am I right? And why do I get this error?
The problem is that you are trying to use a partial specialization of the entire class without having defined the partially-specialized class.
If
printwere itself a function template, the situation would be different, because you can indeed specialize function templates. However, your construction only has the entire class as a template.This means that
template <typename T, int n> class Storage<T, n>andtemplate <int n> class Storage<int, n>are entirely different, unrelated classes. Thus you must first define the latter class:Consider that the partial specialization
Storage<int, n>may be an entirely different class from the primary template, and it may have totally different member functions. The compiler has no way of knowing this until you actually define that class.Following sbi’s comment, here’s one idea:
Instead of the
friendyou could also make the helper function templatestatic, but that might add a lot of code bloat, since you’ll have two static function templates per class type, rather than just two globally.