2

Given the following snippet:

struct A {
  template <class T >
  void doSomething(T t) {
    std::cout << "doSomething() with " << t << std::endl;
  }
};
template <class T>
struct B {
  T val;
};

How can I specialize A::doSomething() for a template B<T> ? The following "naïve" attempt does not compile but might explain what I want to achieve:

template<class T>
void A::doSomething(B<T> t){
  std::cout << "doSomething specialized for B: " << t.val << std::endl;
}

Is what I want to achieve possible ? and if it is what is the syntax ?

UPDATE

Reading this thread I found an alternative way of achieving what I want: Specialize a template with a template

As the syntax is not always easy with templates, here is a working example with different levels of specializations:

#include <iostream>
#include <vector>

namespace details {
template<class T> struct Impl;
}
struct A {
  template <class T >
  void doSomething(T t) {
    details::Impl<T>::f(t);
  }
};
template <class T>
struct B {
  T val;
};
namespace details {
template<class T>
struct Impl {
  static void f(T t){std::cout << "default" << std::endl;}
};
template<template<class> class U, class T>
struct Impl<U<T> > {
  static void f(U<T> b){std::cout << "default for U<T>"<< std::endl;}
};
template<>
void Impl<double>::f(double d) {
  std::cerr << "doSomething with double " << d << std::endl;
}
template<class T>
struct Impl<B<T> > {
  static void f(B<T> b);
};
template<class T> 
void Impl<B<T> >::f(B<T> b) {
  std::cerr << "doSomething with B<T> " << b.val << std::endl;
}
template<> 
void Impl<B<int> >::f(B<int> b) {
  std::cerr << "doSomething with B<int> " << b.val << std::endl;
}
}
template<class T>
struct C {
  T toto;
};
int main() {
  A a;
  a.doSomething(12.0);
  B<double> b;
  b.val = 42.0;
  a.doSomething(b);
  B<int> b2;
  b2.val = 42.0;
  a.doSomething(b2);
  C<int> c;
  a.doSomething(c);
  std::vector<int> v;
  a.doSomething(v);
  return 0;
}
Community
  • 1
  • 1
Charles
  • 125
  • 1
  • 6
  • 1
    Partial template specialization works only for classes. See gfor example http://www.gotw.ca/publications/mill17.htm – marom Jan 08 '16 at 15:30
  • What you're doing is overloading (which is the preferred way) but you also have to declare the function in the class `template void doSomething(B)` – David G Jan 08 '16 at 15:36
  • Possible workaround: Use a template class with a single static member function. `template struct doSomething {static void func(blah) {blah}}` You can make a partial specialization for such class. – HolyBlackCat Jan 08 '16 at 15:38
  • All the suggestions to enclose the function into template class fail to take into account lack of automatic template type deduction in such a case. – SergeyA Jan 08 '16 at 15:43

1 Answers1

2

You can't (partially) specialize it, but you can overload the function. Like following (i made the function a free function to ease on typing):

#include <iostream>

template<class T> struct B { };

template<class T> void doSomething(B<T> t) {  std::cout << "B\n"; }

template <class T> void doSomething(T t) { std::cout << "T\n"; }

int main() {
    int x;
    B<double> k;

    doSomething(x);
    doSomething(k);
}

Output:

T
B
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • thanks, but I can't use a free function (struct A was simplified for the example), and this solution imposes that I declare the two overloaded variants in the the struct. – Charles Jan 08 '16 at 16:52
  • @Charles, yes. Well, than you have no choice but to forgo overloading and use partial specialization of the class. – SergeyA Jan 08 '16 at 16:55