4

Since i cant explain this very well, i will start with a small example right away:

template <class T> void Print(const T& t){t.print1();}
template <class T> void Print(const T& t){t.print2();}

This does not compile:
error C2995: 'void Print(const T &)' : function template has already been defined

So, how can i create a template function which takes any type T as long as that type has a print1 memberfunction OR a print2 memberfunction (no polymorphism) ?

smerlin
  • 6,446
  • 3
  • 35
  • 58

2 Answers2

5

One approach would be to use SFINAE to detect if a function exists ( Is it possible to write a template to check for a function's existence?, SFINAE to check for inherited member functions ), and combine the knowledge with something like Boost.Enable_if.

Community
  • 1
  • 1
UncleBens
  • 40,819
  • 6
  • 57
  • 90
  • 1
    *Just* writing up the examples, but now I'm too lazy. The linked questions have enough information anyway. :) – GManNickG Mar 28 '10 at 21:07
1

@UncleBens: did not want to edit your post, here is an example of code (hopefully ripe for copy/pasting), put it in your post and comment on this answer so that I can delete it :)

template <class T>
class HasPrint1
{
public:
  struct type
  {
    enum { value = ( sizeof(dummy((T*)0)) == sizeof(yes_t) ) };
  };

  typedef char yes_t;
  struct no_t { yes_t[2] m; };

  template <class C>
  static yes_t dummy(C*, size_t = sizeof(&C::print1));

  static no_t dummy(...);
};

// same for HasPrint2


template <class T>
boost::enable_if< HasPrint1<T> > Print(const T& t) { t.print1(); }

template <class T>
boost::enable_if< HasPrint2<T> > Print(const T& t) { t.print2(); }

template <class T>
boost::disable_if< boost::mpl::or_< HasPrint1<T>, HasPrint2<T> > >
Print(const T& t) { std::cout << t << std::endl; }

I took the liberty to add a disable_if option to show the similarity with a if / else if / else block.

I'd be glad for some reviews.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • your HasPrint1 template does not work for me, `dummy` and `yes_t` is not declared in `struct type`. so i moved the private part above the public part but i got: `error: 'dummy' declared as function returning an array` – smerlin Mar 29 '10 at 14:30
  • Good call, I changed `no_t` into a `struct` containing the array and removed the `private` keyword. – Matthieu M. Mar 29 '10 at 14:45