模板专业化类功能

时间:2014-11-19 16:22:34

标签: c++ templates template-specialization

所以我有一个用作数据结构的类,但是如果类存储指针,我希望类中的一个函数表现不同。我想要做的不是返回指针,而是在调用[]运算符时返回对象的引用。

这是

之前的课程
template <typename T>
class CollectionTemplate {
    T ** obItems;
    //other code 

    inline T& operator[](int iIndex)
    {
        return * obItems[iIndex];
    }
};

我想添加这个或类似的东西。这段代码在课堂外面

template<>
ClassA & CollectionTemplate<ClassA*>::operator[](int iIndex)
{
    return *(*obItems[iIndex]);
}

但是当我运行代码时出现此错误

E2428 Templates must be classes or functions

从我所看到的内容我看到人们用功能模板做这个但不是类模板任何关于如何做到这一点的想法都会很棒。

3 个答案:

答案 0 :(得分:2)

您可以将类型检测(指针/参考)委托给一个函数,如下所示。

编辑:static之前的access并不重要,因为access函数无论如何都是内联的。所以我再次删除它。

#include <vector>
#include <iostream>

template <class C>
struct Container {

    template <class T>
    T& access(T& x) {
        return x;
    }
    template <class T>
    T& access(T* x) {
        return *x;
    }

    std::vector<C> m_v;

    decltype(access(C)) operator [] (size_t i) {
        return access(m_v[i]);
    }
};

int main() {
    int i1=1, i2=2;

    Container<int*> cp;
    cp.m_v.push_back(&i1);
    cp.m_v.push_back(&i2);

    std::cout << "ip1=" << cp[0]
                        << "\nip2=" << cp[1];

    Container<int> ci;
    ci.m_v.push_back(i1);
    ci.m_v.push_back(i2);

    std::cout << "\ni1=" << ci[0]
                        << "\ni2=" << ci[1];

    return 0;
}

/**
     Local Variables:
     compile-command: "g++ -std=c++11 test.cc -o a.exe && ./a.exe"
     End:
*/

答案 1 :(得分:1)

您无法专门设计模板中的单个方法。您必须专门化整个模板。您可以通过引入帮助程序来使用另一级别的间接。

template <typename T>
class CollectionTemplate {
    T ** obItems;
    //other code 

    template <typename U>
    struct ItemGetter {
        static U& get(U** items, int index) {
            return * items[index];
         }
    };

    template<>
    struct ItemGetter<ClassA*> {
        static U& get(U** items, int index) {
            return *(*items[index]);
         }
    };

    inline T& operator[](int iIndex)
    {
        return ItemGetter<T>::get(objItems, iIndex);
    }
};

阅读您的一些评论,也许您想要专门方法的不同返回类型?同样的原则也适用:

template <typename T>
class CollectionTemplate {
    T ** obItems;
    //other code 

    template <typename U>
    struct ItemGetter {
        using returnType = U*;
        static U* get(U** items, int index) {
            return * items[index];
         }
    };

    template<>
    struct ItemGetter<ClassA*> {
        using returnType = U&;
        static returnType get(U** items, int index) {
            return *(*items[index]);
         }
    };

    using getter = ItemGetter<T>;

    inline getter::returnType operator[](int iIndex)
    {
        return getter::get(objItems, iIndex);
    }
};

答案 2 :(得分:1)

您可以将公共代码放在基类中,然后部分地专门化一个只实现索引运算符的派生类。这样做的好处是,如果你有一些你想要部分专门化的东西,你可以将它们全部放在派生类中,这样就可以在公共部分和专用部分之间进行相对清晰的分离。 (显然下面的代码不会运行,但会编译。)

template <typename T>
class CollectionTemplate_base {
    protected:
        T ** obItems;
    //other code
};

template <typename T>
class CollectionTemplate : public CollectionTemplate_base<T> {
    public:
        T& operator[](int iIndex) {
            return *this->obItems[iIndex];
        }
};

template <typename T>
class CollectionTemplate<T *> : public CollectionTemplate_base<T *> {
    public:
        T &operator[](int iIndex) {
            return *(*this->obItems[iIndex]);
        }
};

int main() {
    CollectionTemplate<int> c1;
    int i = c1[1];

    CollectionTemplate<int *> c2;
    int j = c2[1];
}