模板函数专门化,c++



我正在练习函数专门化,并且我试图创建一个具有专门打印函数的小存储对象。下面是我的代码:

#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() {...}

最新更新