code duplication in template specialization

C

Christof Warlich

Hi,

I just need a specialization for only one member function of a template
class with _many_ members. Do I really have to duplicate the source code
for all the members, i.e. for those that do not need to be specialized?

E.g. in the example below, I'd like to avoid to redefine member B::g():

#include <stdio.h>
template<int x, typename T, short y> class B {
public:
void f(void) {printf("generic f()\n");}
void g(void) {printf("generic g()\n");}
};
// specialization for T == float
template<int x, short y> class B<x, float, y> {
public:
void f(void) {printf("specialized f()\n");}
void g(void) {printf("generic g()\n");}
};
int main(void) {
B<1, int, 2> b;
b.f();
b.g();
B<1, float, 2> s;
s.f();
s.g();
}

Thanks for any suggestions,

Christof
 
A

Alan Woodland

Christof said:
Hi,

I just need a specialization for only one member function of a template
class with _many_ members. Do I really have to duplicate the source code
for all the members, i.e. for those that do not need to be specialized?

E.g. in the example below, I'd like to avoid to redefine member B::g():

#include <stdio.h>
I'd use cstdio instead of stdio.h. Actually, I'd use iostreams instead
of printf, but...
template<int x, typename T, short y> class B {
public:
void f(void) {printf("generic f()\n");}
void g(void) {printf("generic g()\n");}
};
// specialization for T == float
template<int x, short y> class B<x, float, y> {
public:
void f(void) {printf("specialized f()\n");}
void g(void) {printf("generic g()\n");}
};

I'd use inheritance to work around this I think:

//is saying short legal here? I'm not sure...
template <int x, typename T, short y> class Base {
public:
void g() { printf("generic g()\n"); }
};

template <int x, typename T, short y> class B : public Base<x,T,y> {
public:
void f() {printf("generic f()\n");}
};

template <int x, short y> class B<x, float, y> : public Base<x, float, y> {
public:
void f() {printf("specialized f()\n");}
};

Quite where you choose to specialise, and where you chose to inherit
depends a bit on the actual problem in hand though obviously.
int main(void) {
B<1, int, 2> b;
b.f();
b.g();
B<1, float, 2> s;
s.f();
s.g();
}

Alan
 
V

Victor Bazarov

Christof said:
Hi,

I just need a specialization for only one member function of a
template class with _many_ members. Do I really have to duplicate the
source code for all the members, i.e. for those that do not need to
be specialized?
E.g. in the example below, I'd like to avoid to redefine member
B::g():
#include <stdio.h>
template<int x, typename T, short y> class B {
public:
void f(void) {printf("generic f()\n");}
void g(void) {printf("generic g()\n");}
};
// specialization for T == float
template<int x, short y> class B<x, float, y> {
public:
void f(void) {printf("specialized f()\n");}
void g(void) {printf("generic g()\n");}
};
int main(void) {
B<1, int, 2> b;
b.f();
b.g();
B<1, float, 2> s;
s.f();
s.g();
}

Since you're defining a partial specialisation, you cannot avoid
completely redefining the contents of the class template. You can
split the original template in two and only redefine the class
that contains the member you need ot specialise:

#include <stdio.h>
template<typename T> struct Bf {
void f() {printf("generic f()\n");}
};

template<int x, typename T, short y> class B : public Bf<T> {
public:
void g() {printf("generic g()\n");}
};

// specialization for T == float, but of 'Bf', not 'B'
template<> struct Bf<float> {
void f() {printf("specialized f()\n");}
};

int main() {
B<1, int, 2> b;
b.f();
b.g();
B<1, float, 2> s;
s.f();
s.g();
}

Or you could simply define B<float>::f, and not specialise it:

// replace the Bf<float> specialisation with
template<> void Bf<float>::f() {printf("specialized f()\n");}

since it's now a _full_ specialisation...

(and do drop the habit of putting 'void' inside parentheses, it's
a leftover from C, and isn't needed in C++).

V
 
A

Alf P. Steinbach

* Christof Warlich:
I just need a specialization for only one member function of a template
class with _many_ members. Do I really have to duplicate the source code
for all the members, i.e. for those that do not need to be specialized?
No.


E.g. in the example below, I'd like to avoid to redefine member B::g():

#include <stdio.h>
template<int x, typename T, short y> class B {
public:
void f(void) {printf("generic f()\n");}
void g(void) {printf("generic g()\n");}
};
// specialization for T == float
template<int x, short y> class B<x, float, y> {
public:
void f(void) {printf("specialized f()\n");}
void g(void) {printf("generic g()\n");}
};
int main(void) {
B<1, int, 2> b;
b.f();
b.g();
B<1, float, 2> s;
s.f();
s.g();
}

Thanks for any suggestions,

template< int x, typename T, short y >
class B
{
public:
void f() { say( "generic f()" ); }
void g() { G<x, T, y>::do( *this ); }
};

template< int x, typename T, short y >
struct G
{
static void do( B<x, T, y> const& ) { say( "generic g()\n" ); }
};

template< int x, short y >
struct G<x, float, y>
{
static void do( B<x, float, y> const& ) { say( "g<float>()\n" ); }
}

Or thereabouts -- untested code.

Depending on your actual problem some other refactoring may be much better.

Cheers, & hth.,

- Alf
 
C

Christof Warlich

thanks to all, yes, amazingly easy, inheritance does the trick ....
It's obviously been too late for me today already ;-)
 
A

Alf P. Steinbach

* Christof Warlich:
thanks to all, yes, amazingly easy, inheritance does the trick ....
It's obviously been too late for me today already ;-)

Just make sure it's private inheritance (with a "using" thrown in),
unless you want to express an IsA relationship.

An alternative is to use static member function.

Cheers, & hth.,

- Alf
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top