views:

88

answers:

3

What the question says. In addition, is it possible to do this inline?

Here is a small example just to give an idea...

template<typename T>
class Foo {
 public:
  Foo() :z(0.0) {}

  void do( const Foo<T> &f ) {
    z = f.z;
  }
  // specialize 'do' for Foo<int>, possible inline?

 private:
  T z;
};
+1  A: 

You can sort of get this behavior by making the member function a member function template and using SFINAE (substitution failure is not an error). For example:

template <typename U>
typename std::enable_if<!std::is_integral<U>::value && 
                        std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}

template <typename U>
typename std::enable_if<std::is_integral<U>::value && 
                        std::is_same<T, U>::value, void>::type
f(const Foo<U>& x)
{
}

The is_integral type trait test whether U is an integer type. If it is not, the first is instantiated; if it is, the second is instantiated.

The is_same type trait tests to ensure T and U are the same type. This is used to ensure that the member function template is not instantiated for any type other than Foo<T>.

This example makes use of the C++0x <type_traits> library; Boost also has a type traits library that you can use, which works mostly the same.

James McNellis
Thanks! I have to say though, if the syntax is like that I'm probably going to end up going with my alternatives.
floogads
A: 

You may try to do something like this (didn't test, might not work):

template<typename T>
class Foo {
 public:
  Foo() :z(0.0) {}

  template<typename Ty = T>
  void do( const Foo<T> &f ) {
    z = f.z;
  }

  template<>
  void do<int>( const Foo<T> &f ) {
    //specialized code
  }

 private:
  T z;
};
MeDiCS
A specialization is not needed and this can be accomplished using overloading. The problem with overloading is that you would have to overload the member function for each of the integral types. There might be as many as twelve integral types (or more; I lost track shortly after I ran out of fingers), which is a lot of overloads to have to write.
James McNellis
In fact, it does not work that way. I will never understand why people post code that they don't know is valid. The questioner can do that much too.
Johannes Schaub - litb
There are 2 problems with this: You can't specialize member templates inline and you can't specialize them without fully specializing the containing class.
Georg Fritzsche
+2  A: 

You don't need to do anything complicated. Just use overloading and delegation. Note that we cannot just add an int overload, because when T turns out to be int too, this would be an invalid overload (two functions with the same signature)

template<typename T>
class Foo {
 public:
  Foo() :z(0.0) {}

  void doIt(const Foo<T> &f ) {
    doItImpl(f);
  }

 private:
  template<typename U>
  void doItImpl(const Foo<U> &f) {
    z = f.z;
  }

  void doItImpl(const Foo<int> &f) {
    /* ... */
  }

 private:
  T z;
};

Or, for this case, you can do this by specialization

template<typename T>
class Foo {
 public:
  Foo() :z(0.0) {}

  void doIt(const Foo<T> &f ) {
    z = f.z;
  }

 private:
  T z;
};

template<>
inline void Foo<int>::doIt(const Foo<int> &f) {
  /* ... */
}

Using specialization this way is only possible if all template arguments are fixed. In other words, partially specializing the member function is not possible.

Johannes Schaub - litb