我正在练习函数专门化,并且我试图创建一个具有专门打印函数的小存储对象。下面是我的代码:
#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_ */
我得到这个错误:
../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>’
那么,第一个问题:专门化函数可以在类中实现吗?我试了,但得到了一个错误。第二,为什么我得到了我附加的错误?谢谢!
编辑:我尝试了一些新的东西,有人在这里建议。我已经改变了类内的print只有void print()
,我已经在外面实现了它,所以我可以重载函数。: 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;
}
现在我得到invalid use of incomplete type ‘class Storage<int, size>’
,我在这里写了错误(显然!)我知道这是一个常见的解决方案,对吗?为什么会出现这个错误?
问题是您试图使用整个类的部分专门化,而没有将定义为部分专门化的类。
如果print
本身是一个函数模板,情况将会不同,因为您确实可以专门化函数模板。但是,您的构造只将整个类作为模板。
这意味着template <typename T, int n> class Storage<T, n>
和template <int n> class Storage<int, n>
是完全不同的、不相关的类。因此,您必须首先定义后一个类:
template<int n> class Storage<int, n>
{
// define everything
};
template<int n> void Storage<int, n>::print() { /* implement */ }
考虑部分特化Storage<int, n>
可能是一个与主模板完全不同的类,并且它可能具有完全不同的成员函数。编译器没有办法知道这一点,直到你真正定义了这个类。
根据sbi的评论,这里有一个想法:
//... 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)
{
// ...
}
您也可以使用辅助函数模板static
来代替friend
,但这可能会增加很多代码,因为每个类类型将有两个静态函数模板,而不是全局只有两个。
部分专门化总是需要使用完整的模板,因为它们也定义了一个模板。
所以这行不通:
template <int size> void Storage<int,size>::print()
成员函数的完全特化可以对单个成员函数在行外完成,因为它们定义了函数。
这样就可以了:
template <> void Storage<int,44>::print()
并且不能在主模板中声明/定义任何(部分)专门化。
我不认为你可以在单个方法上使用部分专门化。你只能使用完全专门化。
问题是:为什么要使用指定大小的数组?为什么不直接使用std::vector并让push()函数动态地对其进行大小调整(使用std::vector::push_back())?
我能看到的唯一错误是您的专门化中多余的typename T
。应该是:
template <int size> void Storage<int,size>::print() {...}