specialize template member function of a template class

T

toton

Hi,
I want to specialize template member function of a template class .
It is creating some syntax problem ....
Can anyone say how to do it ?

The class is something like this
template<typename T,typename Alloc = std::allocator<T> >
class CircularBuffer4 {
public:
typedef typename CircularBuffer<T,Alloc>::size_type
size_type;
private:
CircularBuffer<T,Alloc> x_;
CircularBuffer<T,Alloc> y_;
CircularBuffer<T,Alloc> xd_;
CircularBuffer<T,Alloc> yd_;
template<DirectionType dt> const CircularBuffer<T,Alloc>& buf()const;
}
where
enum DirectionType{
dtX,dtY
};
I want to specialize buf for dtX & dtY

template<typename T,typename Alloc>
template<>const CircularBuffer<T,Alloc>&
CircularBuffer4<T,Alloc>::buf<dtX>()const{
return x_;
}
This does not compile,
but,
template<typename T,typename Alloc>
template<DirectionType dt>const CircularBuffer<T,Alloc>&
CircularBuffer4<T,Alloc>::buf()const{
return x_;
}
this compiles ....
In both cases all of the codes are in header (I hadn't made the
specialized template code in a cpp file, hope that doesn't cause
problem)

thanks in advance
abir
 
V

Victor Bazarov

toton said:
I want to specialize template member function of a template class .
It is creating some syntax problem ....
Can anyone say how to do it ?

In order to specialise a member you _must_ specialise the class first.
The class is something like this
template<typename T,typename Alloc = std::allocator<T> >
class CircularBuffer4 {
public:
typedef typename CircularBuffer<T,Alloc>::size_type
size_type;
private:
CircularBuffer<T,Alloc> x_;
CircularBuffer<T,Alloc> y_;
CircularBuffer<T,Alloc> xd_;
CircularBuffer<T,Alloc> yd_;
template<DirectionType dt> const CircularBuffer<T,Alloc>& buf()const;
}
where
enum DirectionType{
dtX,dtY
};
I want to specialize buf for dtX & dtY

Why? How would you use it? Couldn't you simply have two functions,
one named 'buf_dtX' and the other 'buf_dtY'?
template<typename T,typename Alloc>
template<>const CircularBuffer<T,Alloc>&
CircularBuffer4<T,Alloc>::buf<dtX>()const{
return x_;
}
This does not compile,
but,
template<typename T,typename Alloc>
template<DirectionType dt>const CircularBuffer<T,Alloc>&
CircularBuffer4<T,Alloc>::buf()const{
return x_;
}
this compiles ....

Because it's not a specialisation. It's just the definition.
In both cases all of the codes are in header (I hadn't made the
specialized template code in a cpp file, hope that doesn't cause
problem)

V
 
T

toton

"Why? How would you use it? Couldn't you simply have two functions,"
Yes, two function is definitely possible. Just wanted to add little
"sugar" to it.
I have a templated function operate, which operates on dtX & dtY. Both
are called, always.
Thus either I have to write 2 operate functions, or generate 2, if I
dont want to use if else ....
So I generated. Now once operate is generated, I need have template
member as all of these class which it calls, again to avoid if else.

The code flow is something like this (all classes are not defined, but
surely one will get the flow).
void SegmentOperator::eek:perate(store::CC& cc) {
cc_ = &cc;
store::ConstPointRange points = cc.points();
operate<dtX>(points);
operate<dtY>(points);
operate<dtXD>(points);
operate<dtYD>(points);
}
well, I could have written 4 functions instead of generating, or a
single function with a if -else or switch statement.

each template are something like,
template<DirectionType dt>void
SegmentOperator::eek:perate(store::ConstPointRange& points) {
size_t size = points.size();
//Current CC reconstructed Points.
Range range(0,size);
//check the No. of points in CC.
//if No. of points less than 2 than nothing to do.
if (size < 2) {
cc_->addSegment<dt>(store::Segment(cc_,range,stDot));
return;
}
///blah blah blah...
}
Here ConstPointRange is a boost::sub_range (a pair of iterators) ,
Range is typedef of std::pair, Segment & CC are my specialized class.
Here as all of the operations are done in 4 directions always,
sometimes 4 specialization, but mostly through simple template ...
That avoids a switch and throw at default value (a runtime check) , and
makes sure all of the parameters passed as direction are proper.
Now once this is templated, whatever it calls can be templated also.
Like I can write a if with addSegment_x, addSegment_y etc, or even
addSegment(DirectionType dt) . In all cases if-else or switch with
throw is there.

Now it also stores 4 directional data , in form of vector4 or
circular_buffer4 , and each operator needs to take the appropriate
data.
Of course each of the type for the container is specified, using
typedef like typedef PointVector4 Vector4<Point> , but I thought to
implement the templated member for vector4 instead, and use if for all
PointVector4, VelocityVector4 etc.

At present I have a switch at the templated classes, with non
templated member function, but for a non templated class a templated
member function.
I have a bunch of Vector4 classes which are typedef. If I want to
specialize all of them, it will again cause repetition. Rather I want
to tell the compiler that these typedefs are specialization, and make
the 4 template member function for only those typedefs.

I hope, it says my problem to some extent.
Thanks for pleasant listening ....
looking for some advice.

abir
 
V

Victor Bazarov

[...]

Take a look at this, maybe it will help.

template<class T> struct A
{
void func1(int) const;
void func2(int) const;

enum e { one, two, three, four, five };

typedef std::map<e, void (A::*)(int) const > funcmap_t;
static funcmap_t mapping;
static int dummy_mapping_initialiser;
static int doit() {
mapping.insert(make_pair(one, &A::func1));
mapping.insert(make_pair(two, &A::func2));
}

void call_it(e ee, int i) {
(this->*(mapping[ee]))(i);
}

public:
A() {}
void operate(int);
};

template<class T> std::map<e, void (A<T>::*)(int) const > A<T>::mapping;
template<class T> int A<T>::dummy_mapping_initiliaser = A<T>::doit();

template<class T> void A<T>::eek:perate(int blah) {
typename funcmap_t::iterator it = mapping.begin(), e =
mapping.end();
while (it != e) {
call_it(it->first, blah);
++it;
}
}

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top