Partial specialisation

A

Alan Woodland

Hi,

The following code is legal, and works as expected:

#include <iostream>

template <typename T>
class Bar {
};

template <typename T, typename P>
class Foo {
public:
void doStuff();
};


template <typename T, typename P>
void Foo<T, P>::doStuff() {
std::cout << "General" << std::endl;
}

int main() {
Foo<float, Bar<float> > a;
a.doStuff();

Foo<float, float> b;
b.doStuff();

return 0;
}


But none of these specialise the method doStuff():

// Not valid:
template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;
}

// Not valid:
template <typename T, typename P=Bar<T> >
void Foo<T, P>::doStuff() {
std::cout << "Specific" << std::endl;
}

// Not valid:
template <typename T, Bar<T> >
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;
}

Is there a valid way to achieve this without using a non member template
function and calling that from within the generic doStuff()?

Thanks,
Alan
 
V

Victor Bazarov

Alan said:
The following code is legal, and works as expected:

#include <iostream>

template <typename T>
class Bar {
};

template <typename T, typename P>
class Foo {
public:
void doStuff();
};


template <typename T, typename P>
void Foo<T, P>::doStuff() {
std::cout << "General" << std::endl;
}

int main() {
Foo<float, Bar<float> > a;
a.doStuff();

Foo<float, float> b;
b.doStuff();

return 0;
}


But none of these specialise the method doStuff():

// Not valid:
template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;
}

// Not valid:
template <typename T, typename P=Bar<T> >
void Foo<T, P>::doStuff() {
std::cout << "Specific" << std::endl;
}

// Not valid:
template <typename T, Bar<T> >
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;
}

Is there a valid way to achieve this without using a non member
template function and calling that from within the generic doStuff()?

No. What you're attempting to do here is to create an _implicit_
partial specialisation of a class template through defining a single
member of it (and without defining the actual partial specialisation
of the class template). That's impossible. You need to define the
entire class template (by repeating most of it) and then define the
member that is different from the unspecialised template.

V
 
S

siddhu

Hi,

The following code is legal, and works as expected:

#include <iostream>

template <typename T>
class Bar {

};

template <typename T, typename P>
class Foo {
public:
void doStuff();

};

template <typename T, typename P>
void Foo<T, P>::doStuff() {
std::cout << "General" << std::endl;

}

int main() {
Foo<float, Bar<float> > a;
a.doStuff();

Foo<float, float> b;
b.doStuff();

return 0;

}

But none of these specialise the method doStuff():

// Not valid:
template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;

}

// Not valid:
template <typename T, typename P=Bar<T> >
void Foo<T, P>::doStuff() {
std::cout << "Specific" << std::endl;

}

// Not valid:
template <typename T, Bar<T> >
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;

}

Is there a valid way to achieve this without using a non member template
function and calling that from within the generic doStuff()?

Thanks,
Alan

You can not specialize the method but you can specialize the class.
Try this.

template <typename T>
class Foo<T,Bar<T> > {
public:
void doStuff();
};

template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;

}
 
V

Victor Bazarov

siddhu said:
You can not specialize the method but you can specialize the class.
Try this.

template <typename T>
class Foo<T,Bar<T> > {
public:
void doStuff();
};

template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;

}

This is usually a problem if the need is to [partially] specialise
a single member function out of dozens. Having to specialise the
entire class template means you need to repeat all but one functions
and give them /exactly same/ implementation as the non-specialised
template.

V
 
A

Alan Woodland

Victor said:
siddhu said:
You can not specialize the method but you can specialize the class.
Try this.

template <typename T>
class Foo<T,Bar<T> > {
public:
void doStuff();
};

template <typename T>
void Foo<T, Bar<T> >::doStuff() {
std::cout << "Specific" << std::endl;

}

This is usually a problem if the need is to [partially] specialise
a single member function out of dozens. Having to specialise the
entire class template means you need to repeat all but one functions
and give them /exactly same/ implementation as the non-specialised
template.

For reference the solution I went with in the end was:

#include <iostream>

template <typename T>
class Bar {
};

template <typename T, typename P>
class DoStuffImpl {
public:
static void apply() {
std::cout << "General" << std::endl;
}
};

template <typename T>
class DoStuffImpl<T, Bar<T> > {
public:
static void apply() {
std::cout << "Specific" << std::endl;
}
};

template <typename T, typename P>
class Foo {
public:
void doStuff();
};


template <typename T, typename P>
void Foo<T, P>::doStuff() {
DoStuffImpl<T, P>::apply();
}

int main() {
Foo<float, Bar<float> > a;
a.doStuff();

Foo<float, float> b;
b.doStuff();

return 0;
}

Which does what I wanted (i.e. not having to repeat all the other
members) via an additional level of indirection (that probably can be
optimised by a decent compiler anyway)

Thanks,
Alan
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top