Adding methods to template specialization
I have a templated C++ class that exposes a number of methods, e.g
template<int X, int Y>
class MyBuffer {
public:
MyBuffer<X,Y> method1();
};
Now, I want to expose add开发者_运维知识库itional methods to this class if X == Y. I have done this by subclassing MyBuffer,
template<int X>
class MyRegularBuffer : public MyBuffer<X,X> {
public:
MyRegularBuffer method2();
};
Now, the problem is that I want to be able to do e.g.
MyRegularBuffer<2> buf = ...
MyRegularBuffer<2> otherBuf = buf.method1().method2();
But I am not sure how to accomplish this. I tried to think of copy constructors, conversion operators, etc, but my C++ skills are unfortunately a bit rusty.
EDIT: I should add that creation of these objects is relatively cheap (and also, it won't happen a lot), which means it would be OK to do something like this:
MyRegularBuffer<2> buf = ...
MyRegularBuffer<2> temp = buf.method1(); // Implicit conversion
MyRegularBuffer<2> otherBuf = temp.method2();
The question is then, how can I define the conversion like that. The conversion operator needs to be in MyBuffer, I think, but I want it to be available only if X==Y.
I'd go for CRTP here:
template<int X, int Y, class Derived>
struct MyBufferBase {
// common interface:
Derived& method1() { return *static_cast<Derived*>(this); }
};
template<int X, int Y>
struct MyBuffer : MyBufferBase<X, Y, MyBuffer<X,Y> > {
// basic version
};
template<int X>
struct MyRegularBuffer : MyBufferBase<X, X, MyRegularBuffer<X> > {
// extended interface:
MyRegularBuffer& method2() { return *this; }
};
You don't need a separate class to represent the special behaviour. Partial specialization allows you to treat some of the MyBuffer <X,Y> cases specially and give them extra methods.
Keep your original declaration of MyBuffer<X,Y> and add this:
template<int Y>
class MyBuffer<Y, Y> {
public:
MyBuffer<Y,Y> method1();
MyBuffer<Y,Y> method2();
};
MyBuffer<1,2> m12; m12.method2(); // compile fail, as desired, as it doesn't have such a method because 1 != 2
MyBuffer<2,2> m22; m22.method2(); // compile success
Edit: my final lines weren't very useful after all, as pointed out by Georg in the comments, so I've deleted them.
It's possible to do what you want if method1
and method2
return a reference to *this
. Otherwise, you're going to need to either do a conversion, or make method1
virtual.
The trick is to have a MyRegularBuffer::method1
that calls MyBuffer::method1
, then a way to convert the resultant MyBuffer<X,X>
into a MyRegularBuffer<X>
:
template<int X>
class MyRegularBuffer : public MyBuffer<X,X>
{
public:
MyRegularBuffer<X>()
{}
MyRegularBuffer<X>(MyBuffer<X,X>)
{
// copy fields, or whatever
}
MyRegularBuffer<X> method2();
MyRegularBuffer<X> method1()
{
MyRegularBuffer<X> ret(MyBuffer<X,X>::method1());
return(ret);
}
};
精彩评论