How should I do this explicit specialization?
Asked Answered
N

6

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.

Neume answered 25/11, 2010 at 8:1 Comment(2)
Can't you overload doSomething on a tag and have a catch all with ellipsis or generic template?Butta
@Tomek_Didn't get what you mean, by the way the focus is on templates.Neume
C
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.

Cadmium answered 25/11, 2010 at 8:8 Comment(1)
As a side note subclass templates can be explicitly specialized without all their enclosing class templates explicitly specialized.Neume
K
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>()
{
}
Khalif answered 25/11, 2010 at 8:17 Comment(2)
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.Neume
@Pooria: Yes it is true, see icecrime's answer for the reference.Apian
P
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;
};
Pecoraro answered 25/11, 2010 at 8:28 Comment(3)
By the way this gets compiled on visual C++ 2008 due to some bug I guess!! ;) .Neume
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:)Pecoraro
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.Neume
N
0

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

Nickelplate answered 25/11, 2010 at 8:22 Comment(0)
N
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>();
}
Nephrectomy answered 25/11, 2010 at 14:33 Comment(2)
That's not explicit specialization, so no bug at all.Neume
Yes it just defining the templated member funćtion. Tried Nikola Smiljanić and it works with g++.Nephrectomy
N
-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.

Neume answered 25/11, 2010 at 8:23 Comment(4)
On my g++ version it doesn't compile.Nickelplate
why the hell downvote when it gets compiled perfectly on visual C++ 2008?Neume
This one definitely shouldn't work. And in fact it doesn't in MSVC10.Tsunami
It's not valid C++, if it compiles for you it is a compiler extension or a bug (depending on how you look at things).Apian

© 2022 - 2024 — McMap. All rights reserved.