C ++指针模板特化

时间:2015-08-21 14:39:08

标签: c++ templates

我正在尝试设计一个类型为T *的模板类,其声明如下:

template <class T>
class StructParamPublic<T*>
    {
    .....
    protected:
    T* m_pData;
    };

可用于创建像这样的结构

StructParamPublic <FloatArrayStruct*> m_pFloatArray;

,其中

FloatArrayStruct
{
float* pData;
size_t arraySize;
};

但是,当我编译它时,我收到的错误是StructParamPublic不是模板类型。

如果我定义以下模板类

template <class T>
class StructParamPublic
    {
    .....
    protected:
    T m_Data;
    };

然后这个错误消失了。 出于某些设计考虑,我不想将第二个定义添加到框架中。

我的解决方案是想出这样的东西

template <class T>
class StructParamPublic
    {
    .....
    protected:
    T* m_pData;
    };

它编译得很好。

所以我的问题是:模板<class T> class StructParamPublic是某种“基本模板类”和template <class T>class StructParamPublic<T*> 那种类的某种推导?

3 个答案:

答案 0 :(得分:1)

你可以这样做:

template<typename T>
class StructParamPublic;
// ^ This just "forward declares" the class for all possible template values

template<typename U>
class StructParamPublic<U*> {
    ...
};
// ^ This is a partial specialization of the above class template. It will deduce the type of T from the pointer type that you instantiate the template with

如果您这样做,那么语法StructParamPublic<int*>将是合法的,并且当您使用时,它会在模板中将类型T推断为int

一般情况下,当您拥有template<typename T> class < T::dependent_type > { ... };时,您应该使用模板专门化来使其按照您期望的方式工作,并且这要求您首先制作非主流的“主要”模板,即使该主要模板实际上并没有做任何事情(除了作出声明)。

另请注意,您实际上并不需要在此处使用类型特征来强制执行指针类型要求。在上面的代码中,如果您尝试使用非指针类型,它只会找到主模板而不能找到真正的定义。如果您需要,可以在主模板"missing * in StructParamPublic<...>"或类似内容中添加静态断言。

答案 1 :(得分:1)

您无需定义第二个类模板。你可以使用前瞻声明。

template <class T> class StructParamPublic;

然后你可以使用

template <class T>
class StructParamPublic<T*>
    {
    .....
    protected:
    T* m_pData;
    };

答案 2 :(得分:1)

template <class T> class StructParamPublic<T*>;

的专业化
template <class T> class StructParamPublic;

因此,对于您的问题,您有几种可能性:

  • (部分)专业化

    template <class T> class StructParamPublic;
    
    template <class T>
    class StructParamPublic<T*>
    {
    // code
    protected:
        T* m_pData;
    };
    

    StructParamPublic<int>会导致未定义类的错误。

  • static_assert

    template <class T>
    class StructParamPublic
    {
        static_assert(std::is_pointer<T>::type, "type should be a pointer type");
        using value_type = typename std::remove_pointer<T>::type;
    
    // code
    protected:
        T m_pData; // or value_type* m_pData;
    };
    
    由于StructParamPublic<int>

    static_assert会导致干净错误。

  • 或更改参数的含义作为解决方案。

    template <class T>
    class StructParamPublic
    {
        .....
    protected:
        T* m_pData;
    };
    
    此处使用

    StructParamPublic<int>,而之前的解决方案需要StructParamPublic<int*>