Dan
Dan

Reputation: 13412

Template Member Specialization of Template Class

I have a class structure which is

template<int T>
class MyClass {
public:
    MyClass(){};
    ~MyClass(){};

    template<class K> void foo();
};

Now I want to specialize the foo() method based upon the value of the integer used in MyClass<int>, for instance if int the code we have MyClass<2> I want to use a different version of foo<K>() to if I had MyClass<3>. However I want to still have foo<K>() unspecialized on K.

So that would mean something like this would be okay

MyClass<2> myc2;
MyClass<3> myc3;
myc2.foo<SomeClass>();
myc2.foo<SomeOtherClass>();
myc3.foo<SomeClass>();
myc3.foo<SomeOtherClass>();

Is it possible to specialize in this way but not specialize on K? I've tried a few combinations with no success.

Upvotes: 2

Views: 361

Answers (5)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361792

Don't specialize. Just delegate the call to overloaded function as:

template<int T>
class MyClass {
public:
    MyClass(){};
    ~MyClass(){};

    template<class K> 
    void foo()
    {
      foo_worker(static_cast<K*>(0)); //delegate to overloaded function
    }
private:
    template<class K>
    void foo_worker(K*)
    {
        //general code goes here
    } 
    void foo_worker(SomeClass*)
    {
        //code when K = SomeClass
    } 
    void foo_worker(SomeOtherClass*)
    {
        //code when K = SomeOtherClass
    } 
};

And here is how it would work:

  • If K is SomeClass, then foo_worker(SomeClass*) would be called eventually.
  • Else if K is SomeOtherClass, then foo_worker(SomeOtherClass*) would be called.
  • Else the generic foo_worker will be called.

Note the parameter in the foo_worker is used to enable the compiler to select the correct overloaded function.

Upvotes: -1

Branko Dimitrijevic
Branko Dimitrijevic

Reputation: 52157

This works under my Visual C++ 2010:

template<int T>
class MyClass {
public:
    MyClass(){};
    ~MyClass(){};
    template<class K> void foo() {
        std::cout << "foo() for T" << std::endl;
    }
};

template<>
template<class K>
void MyClass<2>::foo() {
    std::cout << "foo() for 2" << std::endl;
}

template<>
template<class K>
void MyClass<3>::foo() {
    std::cout << "foo() for 3" << std::endl;
}

void main() {
    MyClass<1>().foo<int>();
    MyClass<2>().foo<float>();
    MyClass<3>().foo<std::string>();
}

This prints:

foo() for T
foo() for 2
foo() for 3

Upvotes: 1

jrok
jrok

Reputation: 55425

If I understood your question correctly, this is what you want:

template<int T>
class MyClass {
public:
    MyClass(){};
    ~MyClass(){};

    template<class K> void foo();
};

template<int T>
template<class K>
void MyClass<T>::foo()
{
    std::cout << "general form\n";
}

template<>
template<class K>
void MyClass<2>::foo()
{
    std::cout << "MyClass<2>\n";
}

int main()
{
    MyClass<3> c1;
    c1.foo<int>(); // general form
    MyClass<2> c2;
    c2.foo<int>(); // MyClass<2>
    c2.foo<float>(); // MyClass<2>
}

Upvotes: 2

Jon
Jon

Reputation: 1

Problem usually is specialization of template classes, need to specialize the whole class which is inconvenient if the class has a large interface. One way is to provide another level of indirection as below:

#include <iostream>

template<int T>
class MyClass {
public:
    MyClass(){};
    ~MyClass(){};

    class fooImpl;

    template<class K> void foo()
    {
       fooImpl::fn<K>();
    }
};

template<>
class MyClass<2>::fooImpl
{
public:
   template <class K> static void fn()
   {
      std::cout << "two : " << typeid(K).name() << "\n";
   }
};

template<>
class MyClass<3>::fooImpl
{
public:
   template <class K> static void fn()
   {
      std::cout << "three : " << typeid(K).name() << "\n";
   }
};

class SomeClass {};
class SomeOtherClass {};

int main()
{
   MyClass<2> myc2;
   MyClass<3> myc3;
   myc2.foo<SomeClass>();
   myc2.foo<SomeOtherClass>();
   myc3.foo<SomeClass>();
   myc3.foo<SomeOtherClass>();

   return 0;
}

Then you only have to specialize the implementation classes of foo (fooImpl) and not all the other member functions on MyClass you may want to add.

My Compiler gave the following output:

two : class SomeClass
two : class SomeOtherClass
three : class SomeClass
three : class SomeOtherClass

Upvotes: -1

Alex Z
Alex Z

Reputation: 1877

You might try boost::enable_if, it allows to enable or disable particular specializations of classes and methods. Take a look at examples here: http://www.boost.org/doc/libs/1_48_0/libs/utility/enable_if.html

Upvotes: 1

Related Questions