Andry
Andry

Reputation: 16845

How to create specialization for a single method in a templated class in C++?

Many questions have been asked and they are similar to the one I am going to ask here, but they are not the same I think.

I have a templated class:

namespace app {
template <typename T>
class MyCLass {
public:
  void dosome();
  void doother();
}
} /*ns*/

And implementations:

template <typename T>
app::MyClass<T>::dosome() {}
template <typename T>
app::MyClass<T>::doother() {}

When I have an instance of that class to which a char is provided as template parameter, I want function dosome() to behave in a totally different way. But I just want that function to behave differently, everything else must still act the same.

I tried typing:

template<>
app::MyCLass<char>::dosome() {
}

But the compiler tells me that I am trying to create a specialization in a different namespace.

So when I have a code like this:

app::MyCLass<int> a;
app::MyCLass<char> b;
a.dosome(); // This must call the generic template definition
b.dosome(); // This must call the specialization
a.doother(); // This must call the generic template definition
b.doother(); // This must call the generic template definition

In other questions I saw people creating totally different specialization of the entire class. But I only want a specialization of a single method.

Upvotes: 2

Views: 358

Answers (2)

Jarod42
Jarod42

Reputation: 217145

You can do what you want: http://ideone.com/oKTFPC

// Header

namespace My
{

template <typename T>
class MyClass {
public:
    void dosome();
    void doother();
};

template <typename T> void MyClass<T>::dosome() {}
template <typename T> void MyClass<T>::doother() {}

template<> void MyClass<char>::dosome();

}

// cpp or in header

template<>
void My::MyClass<char>::dosome() {
    std::cout << "specialization" << std::endl;
}

or using alternate notation

namespace My {
template<>
void MyClass<char>::dosome() {
    std::cout << "specialization" << std::endl;
}
}

Upvotes: 2

jrok
jrok

Reputation: 55395

One option would be tag dispatching:

template <typename T>
class MyClass {
public:
  void dosome() { dosome_impl( T() ); }

private:

  void dosome_impl(char) { /* char stuff */ }  
  template<typename U>
  void dosome_impl(U) { /* usual stuff */ }
};

Another one is enable_if idiom:

#include <type_traits>

template <typename T>
class MyClass {
public:
  template<typename U = T>
  typename std::enable_if<std::is_same<U,char>::value>::type
  dosome() { /* char stuff */ }

  template<typename U = T>
  typename std::enable_if<!std::is_same<U,char>::value>::type
  dosome() { /* normal stuff */ }
};

And yet another one is to move that single function to a base class that you can specialize:

template <typename T>
struct MyClass_base {
    dosome() { /* usual stuff */ }
};

template<>
struct MyClass_base<char> {
    dosome() { /* char stuff */ } 
};

template <typename T>
class MyClass : private MyClass_Base<T> {
public:
    // nothing special here
};

Upvotes: 2

Related Questions