Reputation: 13412
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
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:
K
is SomeClass
, then foo_worker(SomeClass*)
would be called eventually.K
is SomeOtherClass
, then foo_worker(SomeOtherClass*)
would be called.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
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
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
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
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