开发者

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜