Boost logo

Boost :

From: (nil)
Date: 2000-02-10 15:35:41


As much as I hate to re-open this issue, over lunch I had an odd idea on how
to implement a ctassert. I do not think it is possible to satisfy *all* of
the requirements specified. However, here's a stab at a way to satisfy most
of them.

The idea is to use duplicate typedef declarations, one for a known true
value, and the other for the conditional. If the conditional is false, the
second typedef declaration will be an error. This satisfies:
  (R1) Give an error message *at the line* where the assertion fails.
  (R2) Usable in both declarations and implementations in the same way.
  (R3) No real code should be generated and no storage should be used.
  (R5) Namespaces should be polluted in a minimal way.
   - note: one name ("ctassert_true") is reserved for use, but nothing else
  1) no runtime cost
  2) use anywhere
  3) simple syntax
  4) can use compile-time constants
  5) stop with error
  6) portable
  8) points to correct line

However, it fails:
  (R4) No macros.
  7) good error message
   - the error message will be something along the lines of 'duplicate
definition of ctassert_true'
  9) practical
   - The problem is, BCB4, which I use, has two annoying bugs that prevents
the proper usage of this implementation.

Anyway, here's the code:
-----

namespace boost {
// In the ideal world, ctassert is never instantiated or referenced;
// However, we can provide the usual definitions (i.e., if false,
// can't be instantiated) for use with broken compilers
template<bool> struct ctassert { };
} // namespace boost

#define POSTULATE(cond) \
  typedef ::boost::ctassert<true> ctassert_true; \
  typedef ::boost::ctassert<(cond)> ctassert_true

// Namespace scope
POSTULATE(sizeof(int) == 4);
POSTULATE(sizeof(char) == 1);
//POSTULATE(sizeof(int) == sizeof(char)); // will not compile

// Function (block) scope
void f()
{
  POSTULATE(sizeof(int) == 4);
  POSTULATE(sizeof(char) == 1);
// POSTULATE(sizeof(int) == sizeof(char)); // should not compile
}

struct Bob
{
  private: // can be in private, to avoid namespace pollution
    POSTULATE(sizeof(int) == 4);
    POSTULATE(sizeof(char) == 1);
// POSTULATE(sizeof(int) == sizeof(char); // will not compile
  public:

  // Member function scope: provides access to member variables
  int x;
  char c;
  void f()
  {
    POSTULATE(sizeof(x) == 4);
    POSTULATE(sizeof(c) == 1);
// POSTULATE(sizeof(x) == sizeof(c)); // should not compile
  }
};

// Template class scope
template <class Int, class Char>
struct Bill
{
  private: // can be in private, to avoid namespace pollution
    POSTULATE(sizeof(Int) == 4);
    POSTULATE(sizeof(Char) == 1);
// POSTULATE(sizeof(Int) == sizeof(Char)); // should not compile when
instantiated
  public:

  // Template member function scope: provides access to member variables
  Int x;
  Char c;
  template <class Int2, class Char2>
  void f(Int2 y, Char2 d)
  {
    POSTULATE(sizeof(x) == sizeof(y));
    POSTULATE(sizeof(c) == sizeof(d));
// POSTULATE(sizeof(x) == sizeof(c)); // should not compile when
instantiated
  }
};

void test_Bill() // POSTULATEs are not triggerred until instantiated
{
  Bill<int, char> z;
// Bill<int, int> bad; // will not compile
  int i = 3;
  char ch = 'a';
  z.f(i, ch);
// z.f(i, i); // should not compile
}

-----
Notes for BCB users: right now, typedef redeclarations are fairly broken (as
of BCB4 -- I don't have 5). In function scope, POSTULATE will *never* fail
to compile. In class scope, POSTULATE will *always* fail to compile. There
are work-arounds (for functions, call a do-nothing inlined static function
of ctassert; for classes, derive from ctassert), but they require that the
user explicitly use boost::ctassert<...> in their code, instead of the
cleaner POSTULATEs.

Would someone mind letting me know how well g++ handles this implementation?
I mean, are the workarounds above necessary?

So this isn't a complete solution -- the most annoying thing to me is the
unclear error message, even though the compiler will always choose the
correct line. Anyway, it was just an idea that was different from the
ctassert's suggested by various people so far -- something to think about. .
.

        -Steve


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk