Stuck on partial specialization syntax, as usual.

J

jason.cipriani

I never seem to be able to get this right. Here I have some code:

template <typename T, int N> class A {
void f (T);
};

template <typename T> void A<T,1>::f (T) {
}

template <typename T> void A<T,3>::f (T) {
}

The goal of that code is to partially specialize A<T,N>::f() for
certain values of N, leaving T unconstrained. The syntax is what I
could pick up from this site:

http://www.cprogramming.com/tutorial/template_specialization.html

This code does not compile. Comeau (using whatever the default
settings are when you go to the test drive site) seems to produce the
clearest errors:

"ComeauTest.c", line 5: error: template argument list must match the
parameter list
template <typename T> void A<T,1>::f (T) {

"ComeauTest.c", line 8: error: template argument list must match the
parameter list
template <typename T> void A<T,3>::f (T) {

I can't seem to massage this into compiling. What is the right syntax
for this?

Thanks!
Jason
 
J

jason.cipriani

This code does not compile. Comeau (using whatever the default
settings are when you go to the test drive site) seems to produce the
clearest errors:

"ComeauTest.c", line 5: error: template argument list must match the
parameter list
template <typename T> void A<T,1>::f (T) {

"ComeauTest.c", line 8: error: template argument list must match the
parameter list
template <typename T> void A<T,3>::f (T) {

Well, FWIW here is what GCC says, also (3.4.5 MinGW):

$ g++ pspec.cpp
pspec.cpp:5: error: invalid use of undefined type `class A<T, 1>'
pspec.cpp:1: error: declaration of `class A<T, 1>'
pspec.cpp:5: error: template definition of non-template `void A<T,
1>::f(T)'
pspec.cpp:8: error: invalid use of undefined type `class A<T, 3>'
pspec.cpp:1: error: declaration of `class A<T, 3>'
pspec.cpp:8: error: template definition of non-template `void A<T,
3>::f(T)'

Jason
 
I

Ian Collins

I never seem to be able to get this right. Here I have some code:

template <typename T, int N> class A {
void f (T);
};

template <typename T> void A<T,1>::f (T) {
}
You can't partially specialise an individual member of class template.
 
J

jason.cipriani

Thanks for your reply.

You can't partially specialise an individual member of class template.


:-(

So... if most compilers optimize away constant conditions; can I do
something like this instead:

template <typename T, int N> void A<T,N>::f (T) {
if (N == 1) {
} else if (N == 3) {
}
}

And (probably) not take a performance hit?

Thanks,
Jason
 
J

Jerry Coffin

I never seem to be able to get this right. Here I have some code:

template <typename T, int N> class A {
void f (T);
};

This is a class template.
template <typename T> void A<T,1>::f (T) {
}

This is an attempt at only the member function for a partially
specialized class template -- you need to start with the partial
specialization of the class template itself. Unlike inheritance (for one
example), partial specialization doesn't imply anything about the
partially specialized template having a structure similar to the
unspecialized template. They typically share (at least most of) the same
member functions, but you need to redeclare and re-define each member
function in every partial specialization. The language doesn't prevent
you from defining entirely different member functions in each partial
specialization, if you so choose.

template <class T, int N>
struct A {
void f(T) { std::cout << "Unspecialized.\n"; }
};

template <class T>
struct A<T, 1> {
void f(T) { std::cout << "Spec 1\n"; }
};

template <class T>
struct A<T, 2> {
void f(T) { std::cout << "Spec 2\n"; }
};
 
M

Mark Slater

Thanks for your reply.
:-(

So... if most compilers optimize away constant conditions; can I do
something like this instead:

template <typename T, int N> void A<T,N>::f (T) {
if (N == 1) {
} else if (N == 3) {
}
}

And (probably) not take a performance hit?

template <typename T, int N>
class A {
void f(T);
};

template<typename T>
class A1: public A<T,1> {};

template<typename T>
void A<T,1>::f(T) { /* ... */ }
 
J

jason.cipriani

This is an attempt at only the member function for a partially
specialized class template -- you need to start with the partial
specialization of the class template itself. Unlike inheritance (for one
example), partial specialization doesn't imply anything about the
partially specialized template having a structure similar to the
unspecialized template.

Thanks.

In my case, I have a fairly large and complex template class, but a
small handful of the member functions can be highly optimized for
certain template parameters. I'll have to rethink my design a little
and somehow split things up a little differently; it's very
inconvenient to have to maintain two copies of the code.

I'm almost considering hacking something together right now like:

--- template.h ---

template <class T>
struct A<T, SPECVAL> {
void f(T) { std::cout << "Spec 1\n"; }
};

--- otherfile.h ---

#define SPECVAL 1
#include "template.h"
#undef SPECVAL
#define SPECVAL 2
#include "template.h"

---

I have a feeling that may make me some enemies some day. Too bad I
have a deadline in the morning :-(.

Thanks,
Jason
 
I

Ian Collins

Thanks for your reply.
:-(

So... if most compilers optimize away constant conditions; can I do
something like this instead:

template <typename T, int N> void A<T,N>::f (T) {
if (N == 1) {
} else if (N == 3) {
}
}

And (probably) not take a performance hit?
Or try another level of indirection along the lines of:

#include <iostream>

template <typename T, int N> class A
{
template <int NN> struct X{};

template <typename TT> void fn( T t, TT )
{
std::cout << "called for " << N << std::endl;
}

void fn( T t, X<1> )
{
std::cout << "specialised for 1" << std::endl;
}

public:

void f(T t)
{
fn( t, X<N>() );
}
};

int main()
{
A<int, 42>().f( 0 );
A<int, 1>().f( 0 );

return 0;
}
 
J

James Kanze

Thanks for your reply.
You can't partially specialise an individual member of class template.

So... if most compilers optimize away constant conditions; can I do
something like this instead:[/QUOTE]
template <typename T, int N> void A<T,N>::f (T) {
if (N == 1) {
} else if (N == 3) {
}
}
And (probably) not take a performance hit?

Probably. The usual solution is to use a helper function and a
discriminator class, something like:

template< typename T, int N > class A {
{
template< int N >
class Discriminator;

void f( T t ) {
{
f( t, Discriminator< N >() ) ;
}

void f( T t, Discriminator<1> ) {
// specialization for 1...
}
void f( T t, Discriminator<3> ) {
// specialization for 3...
}
} ;

Presumably, because it is the standard idiom, compilers will
recognize it, and not generate any extra code for the unused
argument (at least as long as the functions are inline).
 
J

Jerry Coffin

[ ... ]
In my case, I have a fairly large and complex template class, but a
small handful of the member functions can be highly optimized for
certain template parameters. I'll have to rethink my design a little
and somehow split things up a little differently; it's very
inconvenient to have to maintain two copies of the code.

It sounds like Ian Collins's suggestion fits your situation almost
perfectly.
 

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,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top