简体   繁体   English

模板专业化类功能

[英]Template specialization class function

So I have a class that I use as a data structure, but I want one of the functions in the class to behave differently if the class is storing pointers. 因此,我有一个用作数据结构的类,但是我希望如果该类存储指针,则该类中的一个函数的行为会有所不同。 What I want to do is instead of returning the pointer I want it to return a reference to the object when the [] operator is called. 我想做的是,而不是返回指针,而是希望它在调用[]运算符时返回对该对象的引用。

This is the class before 这是之前的课程

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

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

I would like to add this or something like this. 我想添加这个或类似的东西。 This code is out side the class 该代码在类之外

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

but I get this error when I run the code 但是运行代码时出现此错误

E2428 Templates must be classes or functions

from what i have read I have seen people do this with function templates but not class templates any idea on how to do this would be awesome. 从我阅读的内容中,我已经看到人们使用功能模板来做到这一点,而不是使用类模板来做到这一点。

You can delegate the type detection (pointer/reference) to a function as shown below. 您可以将类型检测(指针/引用)委托给一个函数,如下所示。

EDIT: The static before access does not really matter since the access functions are inlined anyway. 编辑: static access之前并不重要,因为无论如何都access函数。 So I removed it again. 因此,我再次将其删除。

#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:
*/

You can't specialize only a single method in your template. 您不能仅在模板中专门使用一种方法。 You have to specialize the whole template. 您必须专门化整个模板。 You can use another level of indirection by introducing a helper. 您可以通过引入帮助程序来使用另一种间接级别。

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);
    }
};

Reading some of your comments, maybe you wanted a different return type for the specialized method? 阅读您的一些评论,也许您想要特殊方法的其他返回类型? The same principle holds: 相同的原则成立:

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);
    }
};

You can put the common code in a base class, then partially specialize a derived class that just implements the index operator. 您可以将通用代码放在基类中,然后部分专用于仅实现索引运算符的派生类。 The advantage of this is that if you have a few things that you want to partially specialize, you can just put them all in the derived class, so there's a relatively clean separation between the common part and the specialized part. 这样做的好处是,如果您有一些要部分专门化的东西,则可以将它们全部放入派生类中,因此在公共部分和专门化部分之间存在相对清晰的分隔。 (Obviously the code below won't run, but it will compile.) (显然,下面的代码无法运行,但可以编译。)

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];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM