Boost logo

Boost :

From: Mat Marcus (mmarcus_at_[hidden])
Date: 2002-04-29 14:39:49

I won't be able to check email over the next couple of weeks as
I'll be on vacation, but I wanted to share a little technique
that we (Dietmar Kuehl, Jaako Jarvi, Jermey Siek, and Mat
Marcus) came up with in Curacao. It turns out that in some
limited circumstances it is possible to check whether an
expression is valid at compile time. The example case below is
an is_addable metafunction.

With this technique it could theoretically be possible to write
a metafunction to determine the category of an iterator without
the need for the iterator_category trait. Or we could write
template functions which won't be considered during overload
resolution if the necessary operators are not supported by the
template parameters (using default function argument tricks).

I say theoretically because this technique fails with a
compilation error if the desired operation exists but is
inaccessible. It is also difficult to test for the existence of
regular (non-operator) member functions, or member function
templates, although we made some progress in this area.


//tested on Codewarrior 8 and Comeau

namespace validation
   // Define a type with a ridiculously large
   // size that is unlikely to be returned by a
   // real addition operation

   struct large_type { char mem[65536]; };

   // This class exists to block implicit conversions
   // from working with operator+ below

   struct shim {
      template <typename T>
                                                                         shim(T const&);

   // This will be invoked if no other suitable add exists:
   large_type operator+(shim const&, shim const&);

   template <typename T, typename U>
   struct is_addable
      static T t;
      static U u;
         // If addition doesn't return the large_type than
         // the catch-all was not used
      enum { value = (sizeof(t + u) != sizeof(large_type))};

struct A {};

struct B {
   B operator+(B);

class C {
   C operator+(C);

char test1[validation::is_addable<int, int>::value];
char test2[!validation::is_addable<A, int>::value];
char test3[validation::is_addable<B,B>::value];

// Technique doesn't work when operation exists but
// is inaccessible...
//char test4[add_traits::is_addable<C,C>::value];

Boost list run by bdawes at, gregod at, cpdaniel at, john at