
Below is the compile-time assert I use. Would it be a useful addition to Boost? I know Boost has compile-time assertions, but I think this is different: ----------- template<bool if_> struct assertion { enum { assert }; }; template<> struct assertion<false> {}; template<int if_, int assert_ = assertion<if_ != 0>::assert> struct assert {}; template<typename if_, int assert_ = if_::assert> struct type_assert {}; // they are used via typedef: typedef assert<false> assert_1; typedef type_assert<assertion<false> > assert_2; // type_assert can make nicer error messages: template<typename type_> struct not_integer_type : assertion< std::numeric_limits<type_>::is_integer > {}; typedef type_assert<not_integer_type<float> > assert_3; -------------- Because assertion<false>::assert does not exist, the default template argument to assert is bad when if_ == 0. The "assert_1" and "assert_2" typedefs should make the compiler say something similar to: file.cpp line 123: error: 'assert' is not a member of 'assertion<false>' The "assert_3" typedef should make the compiler say something similar to: file.cpp line 123: error: 'assert' is not a member of 'not_integer_type<float>' It works on the compilers I have: - CodeWarrior 10.0 - GCC 3.2, 3.3, 3.4, 4.0, 4.1 - Intel C++ 9.0 - Visual C++ 7.1, 8.0 Regards, Johan Paulsson

I wrote:
Below is the compile-time assert I use. Would it be a useful addition to Boost?
To make it easier to digest, I put together a minimal web page with - Source code - A test - Compiler errors from the test, using different compilers (It's supposed to make compiler errors). Compiler errors from the same test using BOOST_STATIC_ASSERT, BOOST_MPL_ASSERT and BOOST_MPL_ASSERT_MSG is also included, to make it easy to compare. I think the benefits of my compile time assert is: - No macros - No compiler-specific implementation - It's easy to make useful error-messages Please have a look at <http://www.kuodo.com/code/assert/readme.html> Or download it (12kb) <http://www.kuodo.com/code/assert/assert.zip> Thank You, Johan Paulsson

Johan Paulsson wrote:
I wrote:
Below is the compile-time assert I use. Would it be a useful addition to Boost?
To make it easier to digest, I put together a minimal web page with - Source code - A test - Compiler errors from the test, using different compilers (It's supposed to make compiler errors). Compiler errors from the same test using BOOST_STATIC_ASSERT, BOOST_MPL_ASSERT and BOOST_MPL_ASSERT_MSG is also included, to make it easy to compare.
I think the benefits of my compile time assert is: - No macros - No compiler-specific implementation - It's easy to make useful error-messages
Please have a look at <http://www.kuodo.com/code/assert/readme.html>
Or download it (12kb) <http://www.kuodo.com/code/assert/assert.zip>
Frankly it's hard to choose between them on error message quality (which is to say none are all that good). One of the requirements that came up for static asserts when BOOST_STATIC_ASSERT was talked about was a declaration like syntax, in fact both: static_assert<condition> x; and typedef static_assert<condition> x; were explicitly rejected at the time. I also seem to remember that some compilers at the time evaluated typedefs in a lazy manner: if the typedef was unused then it was never evaluated and the static-assertion was never triggered. That's the reason for some of the convolutions inside static_assert.hpp. I suspect, however, that current compilers have moved away from such "lazyness". And finally, I hope that native static assertions will make it into compilers soon (they're in the C++ std working draft), when that happens it would be trivial to redefine macro based solutions to use the native version: and that really will produce good error messages one hopes! John.

"John Maddock" <john@johnmaddock.co.uk> writes:
Johan Paulsson wrote:
I wrote:
Below is the compile-time assert I use. Would it be a useful addition to Boost?
To make it easier to digest, I put together a minimal web page with - Source code - A test - Compiler errors from the test, using different compilers (It's supposed to make compiler errors). Compiler errors from the same test using BOOST_STATIC_ASSERT, BOOST_MPL_ASSERT and BOOST_MPL_ASSERT_MSG is also included, to make it easy to compare.
I think the benefits of my compile time assert is: - No macros
I don't think that's a very significant advantage.
- No compiler-specific implementation - It's easy to make useful error-messages
Please have a look at <http://www.kuodo.com/code/assert/readme.html>
Or download it (12kb) <http://www.kuodo.com/code/assert/assert.zip>
Frankly it's hard to choose between them on error message quality (which is to say none are all that good).
I think you'd see a much bigger difference in quality if there were a deep instantiation backtrace. With the MPL asserts, the failing condition shows up in the error message itself, rather than in a backtrace frame, which (on GCC for example) can be far, far away from the top of the output. Also, the first test, which simply asserts a bool constant, is not very interesting from an error-message-quality point of view. You can't expect much useful information from such an assertion; it's similar to assert(false); at runtime. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote: > "John Maddock" <john@johnmaddock.co.uk> writes: > >> Johan Paulsson wrote: >>> I wrote: >>>> Below is the compile-time assert I use. >>>> Would it be a useful addition to Boost? >>> To make it easier to digest, I put together a minimal web page with >>> - Source code >>> - A test >>> - Compiler errors from the test, using different compilers (It's >>> supposed to make compiler errors). Compiler errors from the same test >>> using BOOST_STATIC_ASSERT, BOOST_MPL_ASSERT and BOOST_MPL_ASSERT_MSG >>> is >>> also included, to make it easy to compare. >>> >>> I think the benefits of my compile time assert is: >>> - No macros > > I don't think that's a very significant advantage. > You are right, thank you for pointing that out. >>> - No compiler-specific implementation >>> - It's easy to make useful error-messages >>> >>> Please have a look at <http://www.kuodo.com/code/assert/readme.html> >>> >>> Or download it (12kb) <http://www.kuodo.com/code/assert/assert.zip> >> >> Frankly it's hard to choose between them on error message quality (which is >> to say none are all that good). > > I think you'd see a much bigger difference in quality if there were a > deep instantiation backtrace. With the MPL asserts, the failing > condition shows up in the error message itself, rather than in a > backtrace frame, which (on GCC for example) can be far, far away from > the top of the output. I collected some more compiler output. It's not extremely deep but the typenames are long. I hope this is closer to what you would like to see: Directory listing: <http://www.kuodo.com/code/assert/deep> Download (19kb): <http://www.kuodo.com/code/assert/deep/deep.zip> Please note this is plain text, no html. The "readme.txt" file should explain what the other files contain. In this case, with the compilers I used, I do not see a big difference in quality of the error message. > Also, the first test, which simply asserts a bool constant, is not > very interesting from an error-message-quality point of view. You > can't expect much useful information from such an assertion; it's > similar to > > assert(false); > > at runtime. > I agree, I should have left it out of the compiler output. /Johan Paulsson

Johan Paulsson <boost.org@kuodo.com> writes:
In this case, with the compilers I used, I do not see a big difference in quality of the error message.
Of course not, especially because in this case you seem to have left out all but the very useless ASSERT(false) case.
Also, the first test, which simply asserts a bool constant, is not very interesting from an error-message-quality point of view. You can't expect much useful information from such an assertion; it's similar to
assert(false);
at runtime.
I agree, I should have left it out of the compiler output.
So why did you throw out the only assertion that can possibly show useful results? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Johan Paulsson <boost.org@kuodo.com> writes:
In this case, with the compilers I used, I do not see a big difference in quality of the error message.
Of course not, especially because in this case you seem to have left out all but the very useless ASSERT(false) case.
I can find two problems with what I posted. First: I do not mention that the compilations instantiate the code with the compile-time assertions with booth traits_::base = 10 and traits_::base = 16. I suppose this means booth the ASSERT(true) and ASSERT(false) case. Second: My use of: BOOST_MPL_ASSERT((::boost::mpl::integral_c<bool, traits_::base == 10>)); could be improved to something similar to: BOOST_MPL_ASSERT((base_not_10<traits_::base>)); This would produce a compiler error containing something similar to: 'assertion_failed(mpl_::failed************ base_not_10<16>::************)' I think this would have been better as it is similar to what I used with my own implementation. Please accept my apologies. I have removed all files from <http://www.kuodo.com/code/assert/deep/> because I feel they can not be used for a fair comparation of the error messages. If there are more issues, please tell me. The last thing I want to do is upset anyone or spread false information, if I have I am sorry. Thank You, Johan Paulsson

David Abrahams wrote:
Johan Paulsson <boost.org@kuodo.com> writes:
In this case, with the compilers I used, I do not see a big difference in quality of the error message.
Of course not, especially because in this case you seem to have left out all but the very useless ASSERT(false) case.
I made a different, in my opinion much better, test for compile time assertions in recursive templates. I put together a small web-page with source code and output from some compilers. Please have a look at <http://www.kuodo.com/code/assert/recurse/readme.html> Or download it (9kb) <http://www.kuodo.com/code/assert/recurse/recurse.zip> The test can be made to instantiate templates to a certain depth, and compile time assertions can be set to fail when a certain depth is instantiated, in class and/or function scope. The compiler back-trace shows the instatiation-depth (a int template argument), at least on the compilers I have used. In this case, I do see a difference with the Intel compiler. My implementation does not point to the line of the compile-time assert typedef. That is not very nice. The output says: ../recurse.hpp(27): error: class "tests::too_deep_in_function<5>" has no member "assert" If it said 80 instead of 27 it would point to the compile-time assert typedef. David, I think this is what you said in a previous message?
Also, the first test, which simply asserts a bool constant, is not very interesting from an error-message-quality point of view. You can't expect much useful information from such an assertion; it's similar to
assert(false);
at runtime.
I agree, I should have left it out of the compiler output.
So why did you throw out the only assertion that can possibly show useful results?
I think the output from the class-scope assertion that is included in the compiler output is useful, thogether with the source code for the test. I wanted to show, as briefly as possible, the basic usage of my implementation compared to something the readers of this mailing list would recognize. I think it does. It was not my intention to prove one implementation better than the other, or provide a very useful test, and I think I never implied that. Anyway, I am sorry you found it useless. /Johan Paulsson

Johan Paulsson <boost.org@kuodo.com> writes:
I wanted to show, as briefly as possible, the basic usage of my implementation compared to something the readers of this mailing list would recognize. I think it does. It was not my intention to prove one implementation better than the other, or provide a very useful test, and I think I never implied that.
I do think you implied your implementation was better. You seem to be concerned that you have offended somehow, but I have no problem with that implication at all. Your arguments didn't hold up for me, though.
Anyway, I am sorry you found it useless.
No need to apologize. Cheers, -- Dave Abrahams Boost Consulting www.boost-consulting.com

John Maddock wrote:
Johan Paulsson wrote:
I wrote:
Below is the compile-time assert I use. Would it be a useful addition to Boost?
8>< snip
Frankly it's hard to choose between them on error message quality (which is to say none are all that good).
One of the requirements that came up for static asserts when BOOST_STATIC_ASSERT was talked about was a declaration like syntax, in fact both:
static_assert<condition> x;
and
typedef static_assert<condition> x;
were explicitly rejected at the time.
Thank you for looking. I prefer some kind of template, but I now realize most do not.
I also seem to remember that some compilers at the time evaluated typedefs in a lazy manner: if the typedef was unused then it was never evaluated and the static-assertion was never triggered. That's the reason for some of the convolutions inside static_assert.hpp. I suspect, however, that current compilers have moved away from such "lazyness".
That would make my implementation useless. I think it would be interesting to know that a compile-time assert should work on any standard-conforming compiler. I don't know if, for example, typedef-ining an invalid type inside a function, and then not using the type, makes the program "ill formed" and requires a "diagnostic message". Maybe the complie-time asserts in Boost should work on any standard-conforming compiler. I think that would be a good reason to use Boost and not mine. /Johan Paulsson
participants (3)
-
David Abrahams
-
Johan Paulsson
-
John Maddock