Topic: Getting CTAssert to compile


Author: vaps4bm@prism.gatech.edu (Brian McNamara!)
Date: 2000/09/23
Raw View
Scott Meyers <smeyers@aristeia.com> once said:
>  CTAssert< sizeof(Yes) != sizeof(No) > ensureDifferentSizesAssertion;
...
>    private CTAssert< sizeof(checkType(static_cast<T*>(0))) == sizeof(Yes) >
...
>This works perfectly in my head, but it's rejected by MSVC6.4, MWCW 5.3 and
>6, g++ 2.95.2, Borland C++ 5.5.1, and Comeau C++ 4.2.42.  Sigh.  Am I doing
>something invalid in the code above?  If not, does anybody know of a
>compiler that will accept my code?

I am pretty sure your code is valid (I spent a few minutes paging
through the standard), and thus to all the compiler-implementers in the
audience, you've made your point.  :)


Nevertheless, I feel compelled to mention that, as a practical matter,
if you _parenthesize_ constant expressions that are used a non-type
template arguments, then this helps many compilers parse it.

For example, when I changed the first code above to this:

   CTAssert<( sizeof(Yes) != sizeof(No) )> ensureDifferentSizesAssertion;
            ^                           ^
g++ parsed it happily, and when I did it to here:

   private CTAssert<( sizeof(checkType(static_cast<T*>(0))) == sizeof(Yes) )>
                    ^                                                      ^
then g++ did still die, but gracefully, with a "sorry, not implemented"
message.


Slightly more heavyweight, and not quite as usable: if you assign such
expressions to constants, this seems to help a lot.  In other words,
change

   foo< some_const_exp > some_var;

to

   static const int x = some_const_exp;
   foo<x> some_var;

and this makes some compilers (g++, at least) happy in almost all cases.

--
Brian McNamara

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Jan =?iso-8859-1?Q?Dj=E4rv?= <Jan.Djarv@lu.erisoft.se>
Date: 2000/09/20
Raw View
Scott Meyers wrote:


> This works perfectly in my head, but it's rejected by MSVC6.4, MWCW 5.3 and
> 6, g++ 2.95.2, Borland C++ 5.5.1, and Comeau C++ 4.2.42.  Sigh.  Am I doing
> something invalid in the code above?  If not, does anybody know of a
> compiler that will accept my code?

I had to make three changes to make it compile with Gcc 2.95:
>
>   CTAssert< sizeof(Yes) != sizeof(No) > ensureDifferentSizesAssertion;

CTAssert< (bool)(sizeof(Yes) != sizeof(No)) >
ensureDifferentSizesAssertion;

>   class Something:
>     private CTAssert< sizeof(checkType(static_cast<T*>(0))) == sizeof(Yes) >
>   {};

class Something:
   private CTAssert< (bool)(sizeof(checkType((T*)(0)))) == sizeof(Yes) >
{};

Gcc 2.95.2 perhaps don't need the static_cast removed, I don't have that
version available right now.

 Jan D.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Scott Meyers <smeyers@aristeia.com>
Date: 2000/09/19
Raw View
Recently I've been introducing people to template metaprogramming stuff,
and one of the examples I like is showing how to ensure that a template
argument T inherits from some specific base class, e.g., Widget.  This is
the code I've been using:

  // CTAssert = "Compile Time Assertion".  By design, only CTAssert<true> is
  // defined.  Use of CTAssert<false> indicates a violated assertion.
  template<bool> class CTAssert;
  template<> class CTAssert<true> {};

  // The following asserts that shorts and longs are different sizes.  I
  // prefer this to the more theoretically iron-clad use of array types,
  // because this way I don't have to remember the syntax for functions
  // returning references to arrays.
  typedef short Yes;
  typedef long No;
  CTAssert< sizeof(Yes) != sizeof(No) > ensureDifferentSizesAssertion;

  class Widget;

  // For a type T, the version of checkType returning Yes is a better match
  // when T (publicly) inherits from Widget than is the version of checkType
  // returning No.  For all other types, checkType returning No is the better
  // match.
  Yes checkType(const Widget*);
  No  checkType(...);

  // The following class template should be instantiable only when T* is
  // implicitly convertible to Widget*.
  template<typename T>
  class Something:
    private CTAssert< sizeof(checkType(static_cast<T*>(0))) == sizeof(Yes) >
  {};

  class Widget{};
  class Foo: public Widget {};

  // This should compile, because Foo inherits from Widget.
  Something<Foo> s;

This works perfectly in my head, but it's rejected by MSVC6.4, MWCW 5.3 and
6, g++ 2.95.2, Borland C++ 5.5.1, and Comeau C++ 4.2.42.  Sigh.  Am I doing
something invalid in the code above?  If not, does anybody know of a
compiler that will accept my code?

Thanks,

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]