Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding methods to template specialization

Tags:

c++

templates

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 additional 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.

like image 743
Krumelur Avatar asked Jul 29 '10 20:07

Krumelur


People also ask

How do you define a template specialization in C++?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

Can you partially specialize a C++ function template?

You can choose to specialize only some of the parameters of a class template. This is known as partial specialization. Note that function templates cannot be partially specialized; use overloading to achieve the same effect.

Are template specializations inline?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is template specialization used for?

It is possible in C++ to get a special behavior for a particular data type. This is called template specialization. Template allows us to define generic classes and generic functions and thus provide support for generic programming.


2 Answers

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; }
};
like image 94
Georg Fritzsche Avatar answered Sep 18 '22 20:09

Georg Fritzsche


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.

like image 26
Aaron McDaid Avatar answered Sep 20 '22 20:09

Aaron McDaid