Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template method specialization for multiple types

I have a class “A” which exposes the template method foo. Foo has a standard implementation which works fine with B,C. It also has a special implementation for D.

class A
{
  template<typename T>
  void foo()
  {
    //standard implementation
  }

  template<>
  void foo<D>
  {
    //special implementation
  }
}

class B{};
class C{};
class D{};

int main()
{
  A<B> a1;
  A<C> a2;
  A<D> a3;
}

Now, I need to add the class E, which requires for "foo" the same special implementation as D. Is there a way to say something like: For all the types use the standard foo. For D,E (and so on) the special implementation.

class A
{
  template<typename T>
  void foo()
  {
    //standard implementation
  }

  template<>
  void foo<D && E>  <-- PseudoCode - It doesn't work
  {
    //special implementation
  }
}

class B{};
class C{};
class D{};
class E{};

int main()
{
  A<B> a1;
  A<C> a2;
  A<D> a3;
  A<E> a4;
}

I was thinking to use the trait classes. But I was hoping there is something simpler to achieve this. Thanks

like image 886
rdil2503 Avatar asked Oct 29 '15 18:10

rdil2503


People also ask

Can templates be used for user defined data types?

Template in C++is a feature. We write code once and use it for any data type including user defined data types.

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

What is the difference between generic class template and specialization template?

Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.

What is a template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.


1 Answers

Using Walter Brown's (C++1z) void_t.

#include <iostream>
#include <type_traits>

template <typename...>
using void_t = void;

template <typename T, typename = void>
struct has_bar 
  : std::false_type { };

template <typename T>
struct has_bar<T, void_t<decltype( std::declval<T&>().bar() ) > >
  : std::true_type { };

class A {
  public:
    void foo() { };
};

class B {
  public:
    void bar() { };
};

class C {
  public:
    void bar() { };
};

template <typename T> 
typename std::enable_if<!has_bar<T>::value, void>::type
fun(T t) {
  std::cout << "fun" << std::endl;
}

template <typename T>
typename std::enable_if<has_bar<T>::value, void>::type
fun(T t) {
  std::cout << "special fun" << std::endl;
}

The code...

int main(const int argc, const char* argv[argc]) {

  A a;
  B b;
  C c;

  fun(a);
  fun(b);
  fun(c);

  return 0;
}

prints out

fun
special fun
special fun

Note, that does not check any type semantics, so it may be better declaring bar() as an interface and using std::is_base_of.

like image 170
Jason Avatar answered Oct 11 '22 21:10

Jason