Specialization of template functions, C ++

I specialize in functions, and I tried to create a small storage object with a specialized print function. Here is 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, the first question: is it possible to implement specialized functions inside a class? I tried but got an error. Secondly, why am I getting the error I made? Thanks!

EDIT: I tried something new, as someone suggested here. I change the print inside the class only void print() , and I embedded it outside so that 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 this is a general solution, right? And why am I getting this error?

0
source share
4 answers

The problem is that you are trying to use the partial specialization of the entire class without specifying a partially specialized class.

If print itself was a function template, the situation would be different, because you can really specialize function templates. However, your design only has the whole class as a template.

This means that template <typename T, int n> class Storage<T, n> and template <int n> class Storage<int, n> are completely different, unrelated classes. Thus, you must first define the last class:

 template<int n> class Storage<int, n> { // define everything }; template<int n> void Storage<int, n>::print() { /* implement */ } 

Consider that the partial specialization Storage<int, n> may be a completely different class from the main template and may have completely different member functions. The compiler does not know this until you define this class.


Following sbi comment, here is one idea:

 //... in the class definition template<typename S, int m> friend void print_helper(const Storage<S, m> &); template<int m> friend void print_helper(const Storage<int, m> &); void print() { print_helper(*this); } 

 // outside: template <typename S, int size> void print_helper(const Storage<S, size> & s) { // ... } template <int size> void print_helper(const Storage<int, size> & s) { // ... } 

Instead of friend you can also create a static helper function template, but this can add a lot of bloating code, since you will have two static function templates for the class type, and not just two globally.

+3
source

Partial specializations should always use the full template, as they also define the template.

So this will not work:

 template <int size> void Storage<int,size>::print() 

Full specializations of member functions can be performed off-line for individual member functions because they define functions.

So this will work:

 template <> void Storage<int,44>::print() 

And you cannot declare / define any (partial) specializations in the main template.

0
source

I do not think that you can use partial specialization according to one method. You can use only full specialization.

Question: why do you want to use an array with the specified size? Why not just use std :: vector and enable the push () function dynamically (using std :: vector :: push_back ())?

0
source

The only mistake I see is the extraneous typename T in your specialization. It should be:

 template <int size> void Storage<int,size>::print() {...} 
0
source

All Articles