Question

Is following design possible?:

template <typename T>
class Test{
 public:
  template <typename Z>
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

Now if it was possible I'd do some explicit specializations for doSomething so that at the end I'd have some versions like below:

void doSomething<int>(){
 //do something
}
void doSomething<double>(){
 //do something
}
...etc

which seems impossible I can't find any syntax to do the job then I thought maybe the design should be as it follows so that all template arguments should be passed to template class itself:

template <typename T,typename Z>
class Test{
 public:
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};

Then I tried partial specialization which didn't even compile:

template <typename T>
void Test<T,int>::doSomething(){
 //do something
}
template <typename T>
void Test<T,double>::doSomething(){
 //do something
}
...etc

I got the following errors for explicit specialization:
error#1:template argument list following class template name must list parameters in the order used in template parameter list.
error#2:'Container1' :too few template arguments.

Was it helpful?

Solution

In order to explicitly specialize doSomething you have to also explicitly specialize Test.

From 14.7.3/18 :

In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.

OTHER TIPS

You cannot explicitly specialize a member template unless its enclosing class templates are also explicitly specialized.

So only something like this will work:

template<> template<>
void Test<int>::doSomething<int>()
{
}

you can always make the function inline

template <class T>
class Test
{
public:
 template <class Z>
 void doSomething() { cout << "default" << endl; }

 template<>
 void doSomething<int>() { cout << "int" << endl;}
 template<>
 void doSomething<double>() { cout << "double" << endl; }
private:
 T obj;
};

I think this one is picky. I suppose you can't do it, read this.

Not sure if this is a bug in g++ but this compiles and produce what I expect.

#include<typeinfo>
#include<iostream>

template<typename T>
class Test
{
public:
    template<typename Z>
    void doSomething();

private:
    T obj;
};

template<typename T>
template<typename Z>
void Test<T>::doSomething()
{
    Z val;
    std::cout << __func__ << ": type " << typeid(val).name() << std::endl;
}

int main(int argc, char *argv[])
{
    Test<double> a;
    a.doSomething<int>();
    a.doSomething<double>();
}

icecrime posted a temporary answer and it gets compiled due to some bug probably by visual C++ 2008:

template <typename T>
class Test{
 public:
  template <typename Z>
  void doSomething();
  //rest of things
 private:
  T obj;
  //some things
};
template <>
template <typename T>
void Test<T>::doSomething<int>(){
 //do something
}

Check his current answer though. The funny thing at least with VC++ 2008 is, no problem compiling when specializing with inline definitions, but for specializations with not-inline definitions once there's more than one version it doesn't get compiled successfully.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top