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 ]