views:

477

answers:

6

Templates are both the blessing and curse of C++. Someone hates them, someone loves them. For those of you are in the latter group, whats your favorite template "hack", and what does it do?

I'll start with my personal favorite, the "friender". This template allowes access to protected members - which I very frequently use for unittesting (lets not get into a discussion about if unit tests should be used like this).

template<typename T>
class FriendIdentity {
public:
  typedef T me;
};

template<class ToFriend, typename ParentClass>
class Friender: public ParentClass
{
public:
  Friender() {}
  virtual ~Friender() {}
private:
// MSVC != GCC
#ifdef _MSC_VER
  friend ToFriend;
#else
  friend class FriendIdentity<ToFriend>::me;
#endif
};

template<typename Tester, typename ParentClass>
Friender<Tester, ParentClass> & 
friendMe(Tester * me, ParentClass & instance)
{
    return (Friender<Tester, ParentClass> &)(instance);
}

Usage:

friendMe(this, someObject).someProtectedFunction();
+2  A: 

Most SFINAE based patterns are basically hacks for me, yet i wouldn't want to miss them. Slightly modified example from Once, Weakly:

struct yes { char a;    };
struct no  { yes  a[2]; };

template <class T>
struct is_class {
    template <class C> static yes test(int C::*);
    template <class C> static no  test(...);
    static const bool result = (sizeof(test<T>(0)) == sizeof(yes));
};
Georg Fritzsche
+1  A: 

I guess I love them and hate them.

It's nice to be able to specialize on another template and provide a default implementation.

template <typename type, class AllocationClass=StandardAllocation> class Array
Charles Eli Cheese
A: 

CGAL is basically one great big template hack.

But if I had to pick one from in there, it would be this: http://www.cgal.org/Manual/last/doc_html/cgal_manual/Triangulation_2/Chapter_main.html

Parameterised as to the kind of numbers and algebraic field it will work on.

Andrew McGregor
+2  A: 

Since templates are Turing complete, type-based computation is my favorite form of template abuse.

namespace Church {
  template <typename X, typename Y>
  struct True {
    typedef X N1;
  };

  template <typename X, typename Y>
   struct False {
     typedef Y N1;
  };

  template <template<typename X, typename Y> class B>
  struct Not {
    template <typename X, typename Y> 
    struct N2 {
      typedef typename B<Y, X>::N1 N1;
    };
  };


  template <template<typename X, typename Y> class B, typename X, typename Y>
  struct IfElse {
    typedef typename B<X, Y>::N1 N1;
  };
...

With some compilers, performance is competitive with Intercal.

outis
+2  A: 

Mixins. Here we define a DistanceMixin class that can be applied to any class that offers a pair of getX(), getY() methods.

template<typename T>
struct DistanceMixin : T {
   double distance() { return sqrt(getX()*getX() + getY()*getY()); }
};


struct Point {
   int getX() { return x; } 
   int getY() { return y; }

   Point(int x_, int y_) : x(x_), y(y_) { }

   private: int x, y;
};


typedef DistanceMixin<Point> PointWithDistance;
Itay
A: 

I know it seems kind of simplistic, but I like how you can make only specializations usable by making some part of the generic class inaccessible to client code.

Permaquid