6

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.

Pooria
  • 2,017
  • 1
  • 19
  • 37

6 Answers6

6

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.

icecrime
  • 74,451
  • 13
  • 99
  • 111
  • As a side note subclass templates can be explicitly specialized without all their enclosing class templates explicitly specialized. – Pooria Jul 29 '11 at 09:10
2

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>()
{
}
Nikola Smiljanić
  • 26,745
  • 6
  • 48
  • 60
  • Smiljanic_"You cannot explicitly specialize a member template unless its enclosing class templates are also explicitly specialized." No that's not right, check my answer. – Pooria Nov 25 '10 at 08:24
  • 3
    @Pooria: Yes it is true, see icecrime's answer for the reference. – CB Bailey Nov 25 '10 at 08:31
1

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;
};
hidayat
  • 9,493
  • 13
  • 51
  • 66
  • 1
    By the way this gets compiled on visual C++ 2008 due to some bug I guess!! ;) . – Pooria Nov 25 '10 at 09:11
  • it compiled for me also in visual C++ 2010, thats why i wrote it. It also works if you run it in visual C++ 2010, so I do not deserve -1:) – hidayat Nov 25 '10 at 10:08
  • 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. – Pooria Nov 25 '10 at 13:37
0

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

Simone
  • 11,655
  • 1
  • 30
  • 43
0

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>();
}
Tobias
  • 835
  • 1
  • 6
  • 11
-2

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.

Pooria
  • 2,017
  • 1
  • 19
  • 37