I was wondering if I partially specialize a class (which I'm understanding to mean hardcode some of the template parameters?) if I have to implement all functions or if I can just implement some functions. I put together a demo:

http://programmingexamples.net/index.php?title=CPP/Templates/PartialClassSpecialization

Where in the main class definition there are two functions, and then only one of them gets specialized in the <T,int> specialization.

However, I'm getting an error which I don't believe has to do with my original question :

on this line

class Point<T, int>

I get

Point.h:16: error: template parameters not used in partial specialization:
Point.h:16: error:         ‘<anonymous>’

I assume it's just a syntax problem? But for some reason I haven't been able to find a clear demonstration of this.

Can anyone see the problem?

Thanks,

David

You need to omit the specialized type from the template <...> declaration. See my edit on your example. As here:

template<typename T>  //the types in here are only those that are unknown.
class Point<T, int>
{
  void function1();
};

//similarly:
template<>  //no type is unknown (full spec.) but you still need this.
class Point<float, int>
{
  void function2();
};

Thanks Mike. Now that it gets past my syntax issue, I get the error I was expecting:

PartialClassSpecialization.cpp:14: error: ‘class Point<int, int>’ has no member named ‘function2’

so does this mean that I indeed must partially specialize EVERY class member? I.e. is there no way to instruct it to use the default template<typename T, typename U> for <T, int> unless it has been specialized?

>>so does this mean that I indeed must partially specialize EVERY class member?

Yes. What you are doing is specializing the entire class, it redefines it completely, so function2 does not exist in the partial specialization unless you redeclare it. But you can specialize the member only (here is a good article):

template<typename T, typename U>
class Point<T, U>
{
  void function1();
  void function2();
};

template<typename T, typename U>
void Point<T, U>::function1() { ... };

template<typename T, typename U>
void Point<T, U>::function2() { ... };

template<typename T>
void Point<T, int>::function1() { ... specialization ... };

PS. auto_ptr has been deprecated by unique_ptr.

Comments
As always, an excellent response!

I guess I jumped the gun. First, shouldn't this:

class Point<T, U>

be

class Point

?

Second, I get

Point.h:22: error: invalid use of incomplete type ‘class Point<T, int>’

on

template<typename T>
void Point<T, int>::function1() { };

Thoughts?

Edited 5 Years Ago by daviddoria: n/a

Oh.. sorry, you're right. You can't do a partial specialization of only a member function (but you can do a full specialization). This is one of those annoying C++ template rules ("The members of a class template partial specialization are unrelated to the members of the primary template").

I should have known, I just answered a question on SO about this specific problem. To avoid having to redefine all the member functions for each partial specialization, the solution, besides using a mixin pattern, is to use a Sfinae method. As such:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/config.hpp>

template <typename T>
struct is_int { BOOST_STATIC_CONSTANT(bool, value = false ); };

template <>
struct is_int<int> { BOOST_STATIC_CONSTANT(bool, value = true ); };

template <typename T, typename U>
struct Point {
  void function1() { };
  void function2() { function2_impl<U>(); };

  template <typename B>
  typename boost::enable_if< is_int<B>, void>::type function2_impl() {
    std::cout << "'int' partial specialization" << std::endl;
  };

  template <typename B>
  typename boost::disable_if< is_int<B>, void>::type function2_impl() {
    std::cout << "primary template" << std::endl;
  };
};

int main() {
  Point<float,float> a;
  Point<float,int> b;

  a.function2();
  b.function2();
};

If I remember right, partial template specialization is in the C++0x standard. I don't know if you can do it on one member function like you want though. Haven't looked into it yet as afaik it's not implemented yet in VS.

Also, the enable_if stuff Mike mentioned is in C++0x, and already implemented in VS2010.

The code I posted works on C++03 (with Boost) (but, as always, it could not work on MSVC compilers, especially prior to 2008, because MSVC is just crap when it comes to template support).

And I have checked in C++0x standard (latest draft), and the rules for partial specialization will not change at all (not even for function templates!).

Edited 5 Years Ago by mike_2000_17: n/a

This article has been dead for over six months. Start a new discussion instead.