[英]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.