From 1df0bf80bc6bc996bd4c0dfe229626e98fc845bb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 14 Nov 2010 18:37:37 +0000 Subject: [PATCH 01/19] Stop inspect complaining that assert is used in BOOST_ASSERT. [SVN r66574] --- include/boost/assert.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index c227f17..584a756 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -13,6 +13,12 @@ // See http://www.boost.org/libs/utility/assert.html for documentation. // +// +// Stop inspect complaining about use of 'assert': +// +// boostinspect:naassert_macro +// + #undef BOOST_ASSERT #if defined(BOOST_DISABLE_ASSERTS) From 636283d7c2bf68d0b259ceca9d5a1d27b9363df5 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Thu, 16 Dec 2010 17:30:46 +0000 Subject: [PATCH 02/19] Limit warning suppression to old versions of VC++, fixes #4432 [SVN r67278] --- include/boost/operators.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index 4b47ba4..b524cee 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -8,6 +8,8 @@ // See http://www.boost.org/libs/utility/operators.htm for documentation. // Revision History +// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++ +// (Matthew Bradbury, fixes #4432) // 07 Aug 08 Added "euclidean" spelling. (Daniel Frey) // 03 Apr 08 Make sure "convertible to bool" is sufficient // for T::operator<, etc. (Daniel Frey) @@ -88,7 +90,7 @@ # pragma set woff 1234 #endif -#if defined(BOOST_MSVC) +#if BOOST_WORKAROUND(BOOST_MSVC, < 1600) # pragma warning( disable : 4284 ) // complaint about return type of #endif // operator-> not begin a UDT From 11d50ecb9f48791bc66751eafa8789d8f08c41f2 Mon Sep 17 00:00:00 2001 From: Bryce Adelstein-Lelbach Date: Fri, 14 Jan 2011 02:35:58 +0000 Subject: [PATCH 03/19] Replacing the use of with across Boost. On Linux, GNU's libstdc++, which is the default stdlib for icc and clang, cannot parse the header in version 4.5+ (which thankfully neither compiler advises the use of yet), as it's original C++98-friendly implementation has been replaced with a gnu++0x implementation. is a portable implementation of , providing boost::detail::setfill, boost::detail::setbase, boost::detail::setw, boost::detail::setprecision, boost::detail::setiosflags and boost::detail::resetiosflags. [SVN r68140] --- call_traits_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/call_traits_test.cpp b/call_traits_test.cpp index 72852c4..ae1b93a 100644 --- a/call_traits_test.cpp +++ b/call_traits_test.cpp @@ -13,7 +13,7 @@ // Enabled extra tests for VC6. #include -#include +#include #include #include #include From 58bb88d4bdf82e7565c88a7953e91c725e470bd8 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 15 Jan 2011 08:11:51 +0000 Subject: [PATCH 04/19] Revert [67111] (addition of boost/detail/iomanip.hpp) and all the commits that depend on it. ([68137], [68140], [68141], [68154], and [68165]). [SVN r68168] --- call_traits_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/call_traits_test.cpp b/call_traits_test.cpp index ae1b93a..72852c4 100644 --- a/call_traits_test.cpp +++ b/call_traits_test.cpp @@ -13,7 +13,7 @@ // Enabled extra tests for VC6. #include -#include +#include #include #include #include From c58748cfd9a185b2f04f3495dba25ac96e1929e2 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sat, 22 Jan 2011 22:18:48 +0000 Subject: [PATCH 05/19] use declval to fix #5098 [SVN r68373] --- .../utility/detail/result_of_iterate.hpp | 20 +++++++------------ include/boost/utility/result_of.hpp | 3 +++ test/result_of_test.cpp | 18 +++++++++++++++++ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 035bf19..1ec857a 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -35,10 +35,7 @@ struct tr1_result_of #if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) -// As of N2588, C++0x result_of only supports function call -// expressions of the form f(x). This precludes support for member -// function pointers, which are invoked with expressions of the form -// o->*f(x). This implementation supports both. +// Uses declval following N3225 20.7.7.6 when F is not a pointer. template struct result_of @@ -56,18 +53,15 @@ struct result_of namespace detail { -# define BOOST_RESULT_OF_STATIC_MEMBERS(z, n, _) \ - static T ## n t ## n; \ - /**/ - template -class cpp0x_result_of_impl +struct cpp0x_result_of_impl { - static F f; - BOOST_PP_REPEAT(BOOST_PP_ITERATION(), BOOST_RESULT_OF_STATIC_MEMBERS, _) -public: - typedef decltype(f(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),t))) type; + typedef decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), declval() BOOST_PP_INTERCEPT) + ) + ) type; }; } // namespace detail diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 9a42fd2..41cc176 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -22,6 +24,7 @@ #include #include #include +#include #ifndef BOOST_RESULT_OF_NUM_ARGS # define BOOST_RESULT_OF_NUM_ARGS 10 diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index a282a75..39f6c3b 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -98,6 +98,11 @@ struct no_result_type_or_result_of unsigned int operator()(); unsigned short operator()() volatile; const unsigned short operator()() const volatile; +#if !defined(BOOST_NO_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif }; template @@ -108,6 +113,11 @@ struct no_result_type_or_result_of_template unsigned int operator()(); unsigned short operator()() volatile; const unsigned short operator()() const volatile; +#if !defined(BOOST_NO_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif }; struct X {}; @@ -232,6 +242,14 @@ int main() BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, unsigned short>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, const unsigned short>::value)); +#if !defined(BOOST_NO_RVALUE_REFERENCES) + BOOST_STATIC_ASSERT((is_same::type, short>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, long>::value)); + BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value)); +#endif #endif return 0; From 87875cadda5a850ec2f7ba2d09024369f4bc5a6e Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 24 Jan 2011 15:37:13 +0000 Subject: [PATCH 06/19] Add BOOST_ASSERT_MSG. Add macros to configure output stream. [SVN r68414] --- assert.html | 74 ++++++++++++++++++++++++++++++----- assert_test.cpp | 45 ++++++++++++++++++++++ include/boost/assert.hpp | 83 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 188 insertions(+), 14 deletions(-) diff --git a/assert.html b/assert.html index a970cef..aa3cbf2 100644 --- a/assert.html +++ b/assert.html @@ -17,36 +17,89 @@   +

+ BOOST_ASSERT
+ BOOST_ASSERT_MSG
+ BOOST_VERIFY

+ +

BOOST_ASSERT

The header <boost/assert.hpp> defines the macro BOOST_ASSERT, which is similar to the standard assert macro defined in <cassert>. - The macro is intended to be used in Boost libraries. + The macro is intended to be used in both Boost libraries and user + code.

By default, BOOST_ASSERT(expr) is equivalent to assert(expr).

-

When the macro BOOST_DISABLE_ASSERTS is defined when <boost/assert.hpp> +

If the macro BOOST_DISABLE_ASSERTS is defined when <boost/assert.hpp> is included, BOOST_ASSERT(expr) is defined as ((void)0). This allows users to selectively disable BOOST_ASSERT without affecting the definition of the standard assert.

-

When the macro BOOST_ENABLE_ASSERT_HANDLER is defined when <boost/assert.hpp> +

If the macro BOOST_ENABLE_ASSERT_HANDLER is defined when <boost/assert.hpp> is included, BOOST_ASSERT(expr) evaluates expr and, if the result is false, evaluates the expression

+

::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)

+

assertion_failed is declared in <boost/assert.hpp> as

-
-namespace boost
+		
+
namespace boost
 {
-
-void assertion_failed(char const * expr, char const * function, char const * file, long line);
-
+  void assertion_failed(char const * expr, char const * function, char const * file, long line);
 }
 
+

but it is never defined. The user is expected to supply an appropriate definition.

As is the case with <cassert>, <boost/assert.hpp> can be included multiple times in a single translation unit. BOOST_ASSERT will be redefined each time as specified above.

+ +

BOOST_ASSERT_MSG

+

+ The header <boost/assert.hpp> defines the macro BOOST_ASSERT_MSG, + which is similar to the standard assert macro defined in <cassert>, + but with an additional macro parameter supplying an error message. The macro is intended to be used in both Boost libraries + and user code. +

+

BOOST_ASSERT_MSG(expr, msg) is equivalent to + ((void)0) if BOOST_DISABLE_ASSERTS or NDEBUG are + defined or expr evaluates to true. If those + macros and BOOST_ENABLE_ASSERT_MSG_HANDLER are not + defined, and expr evaluates to false, an error + message that includes #expr, msg, BOOST_CURRENT_FUNCTION, + __FILE__, and __LINE__ is sent to output stream + BOOST_ASSERT_MSG_OSTREAM + and std::abort() is called.

+

BOOST_ASSERT_MSG_OSTREAM defines the output stream. It defaults to std::cerr. + Integrated development environments (IDE's) like Microsoft Visual Studio + may produce easier to understand output if messages go to a different + stream, such as std::cout. Users may define BOOST_ASSERT_MSG_OSTREAM before including <boost/assert.hpp> + to specify a different output stream. 

+

If the macro BOOST_ENABLE_ASSERT_MSG_HANDLER is defined when <boost/assert.hpp> + is included, instead of sending a error message to an output + stream, this expression is evaluated

+
+

::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, + __FILE__, __LINE__)

+
+

assertion_failed_msg is declared in <boost/assert.hpp> + as

+
+
namespace boost
+{
+  void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line);
+}
+
+
+

but it is never defined. The user is expected to supply an appropriate + definition.

+

As is the case with <cassert>, <boost/assert.hpp> + can be included multiple times in a single translation unit. BOOST_ASSERT_MSG + will be redefined each time as specified above.

+ +

BOOST_VERIFY

<boost/assert.hpp> also defines the macro BOOST_VERIFY. It has exactly the same behavior as BOOST_ASSERT, except that the expression that is passed to BOOST_VERIFY is always @@ -54,8 +107,9 @@ void assertion_failed(char const * expr, char const * function, char const * fil effects; it can also help suppress warnings about unused variables when the only use of the variable is inside an assertion.


- Copyright © 2002, 2007 by Peter Dimov. Distributed under the Boost Software + Copyright © 2002, 2007 by Peter Dimov.  Copyright © 2011 + by Beman Dawes. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.

- + \ No newline at end of file diff --git a/assert_test.cpp b/assert_test.cpp index 693adc4..a0e1e04 100644 --- a/assert_test.cpp +++ b/assert_test.cpp @@ -2,6 +2,7 @@ // assert_test.cpp - a test for boost/assert.hpp // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (2) Beman Dawes 2011 // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -20,6 +21,11 @@ void test_default() BOOST_ASSERT(x); BOOST_ASSERT(x == 1); BOOST_ASSERT(&x); + + BOOST_ASSERT_MSG(1, "msg"); + BOOST_ASSERT_MSG(x, "msg"); + BOOST_ASSERT_MSG(x == 1, "msg"); + BOOST_ASSERT_MSG(&x, "msg"); } #define BOOST_DISABLE_ASSERTS @@ -34,13 +40,23 @@ void test_disabled() BOOST_ASSERT(x == 1); BOOST_ASSERT(&x); + BOOST_ASSERT_MSG(1, "msg"); + BOOST_ASSERT_MSG(x, "msg"); + BOOST_ASSERT_MSG(x == 1, "msg"); + BOOST_ASSERT_MSG(&x, "msg"); + BOOST_ASSERT(0); BOOST_ASSERT(!x); BOOST_ASSERT(x == 0); + BOOST_ASSERT_MSG(0, "msg"); + BOOST_ASSERT_MSG(!x, "msg"); + BOOST_ASSERT_MSG(x == 0, "msg"); + void * p = 0; BOOST_ASSERT(p); + BOOST_ASSERT_MSG(p, "msg"); // supress warnings p = &x; @@ -50,11 +66,13 @@ void test_disabled() #undef BOOST_DISABLE_ASSERTS #define BOOST_ENABLE_ASSERT_HANDLER +#define BOOST_ENABLE_ASSERT_MSG_HANDLER #include #include #include int handler_invoked = 0; +int msg_handler_invoked = 0; void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) { @@ -66,11 +84,24 @@ void boost::assertion_failed(char const * expr, char const * function, char cons ++handler_invoked; } +void boost::assertion_failed_msg(char const * expr, char const * msg, char const * function, + char const * file, long line) +{ +#if !defined(BOOST_NO_STDC_NAMESPACE) + using std::printf; +#endif + + printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", + expr, msg, function, file, line); + ++msg_handler_invoked; +} + struct X { static void f() { BOOST_ASSERT(0); + BOOST_ASSERT_MSG(0, "msg f()"); } }; @@ -83,21 +114,35 @@ void test_handler() BOOST_ASSERT(x == 1); BOOST_ASSERT(&x); + BOOST_ASSERT_MSG(1, "msg2"); + BOOST_ASSERT_MSG(x, "msg3"); + BOOST_ASSERT_MSG(x == 1, "msg4"); + BOOST_ASSERT_MSG(&x, "msg5"); + BOOST_ASSERT(0); BOOST_ASSERT(!x); BOOST_ASSERT(x == 0); + BOOST_ASSERT_MSG(0,"msg 0"); + BOOST_ASSERT_MSG(!x, "msg !x"); + BOOST_ASSERT_MSG(x == 0, "msg x == 0"); + void * p = 0; BOOST_ASSERT(p); + BOOST_ASSERT_MSG(p, "msg p"); X::f(); BOOST_ASSERT(handler_invoked == 5); BOOST_TEST(handler_invoked == 5); + + BOOST_ASSERT_MSG(msg_handler_invoked == 5, "msg_handler_invoked count is wrong"); + BOOST_TEST(msg_handler_invoked == 5); } #undef BOOST_ENABLE_ASSERT_HANDLER +#undef BOOST_ENABLE_ASSERT_MSG_HANDLER int main() { diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index 584a756..a04e2e4 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -1,8 +1,11 @@ // // boost/assert.hpp - BOOST_ASSERT(expr) +// BOOST_ASSERT_MSG(expr, msg) +// BOOST_VERIFY(expr) // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2007 Peter Dimov +// Copyright (c) Beman Dawes 2011 // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -19,6 +22,10 @@ // boostinspect:naassert_macro // +//--------------------------------------------------------------------------------------// +// BOOST_ASSERT // +//--------------------------------------------------------------------------------------// + #undef BOOST_ASSERT #if defined(BOOST_DISABLE_ASSERTS) @@ -31,18 +38,86 @@ namespace boost { - -void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined - + void assertion_failed(char const * expr, + char const * function, char const * file, long line); // user defined } // namespace boost -#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) +#define BOOST_ASSERT(expr) ((expr) \ + ? ((void)0) \ + : ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) #else # include // .h to support old libraries w/o - effect is the same # define BOOST_ASSERT(expr) assert(expr) #endif +//--------------------------------------------------------------------------------------// +// BOOST_ASSERT_MSG // +//--------------------------------------------------------------------------------------// + +# undef BOOST_ASSERT_MSG + +#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG) + + #define BOOST_ASSERT_MSG(expr, msg) ((void)0) + +#elif defined(BOOST_ENABLE_ASSERT_MSG_HANDLER) + + #include + + namespace boost + { + void assertion_failed_msg(char const * expr, char const * msg, + char const * function, char const * file, long line); // user defined + } // namespace boost + + #define BOOST_ASSERT_MSG(expr, msg) ((expr) \ + ? ((void)0) \ + : ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) + +#else + #ifndef BOOST_ASSERT_HPP + #define BOOST_ASSERT_HPP + #include + #include + #include + + // IDE's like Visual Studio perform better if output goes to std::cout or + // some other stream, so allow user to configure output stream: + #ifndef BOOST_ASSERT_MSG_OSTREAM + # define BOOST_ASSERT_MSG_OSTREAM std::cerr + #endif + + namespace boost + { + namespace assertion + { + namespace detail + { + inline void assertion_failed_msg(char const * expr, char const * msg, char const * function, + char const * file, long line) + { + BOOST_ASSERT_MSG_OSTREAM + << "***** Internal Program Error - assertion (" << expr << ") failed in " + << function << ":\n" + << file << '(' << line << "): " << msg << std::endl; + std::abort(); + } + } // detail + } // assertion + } // detail + #endif + + #define BOOST_ASSERT_MSG(expr, msg) ((expr) \ + ? ((void)0) \ + : ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \ + BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) +#endif + +//--------------------------------------------------------------------------------------// +// BOOST_VERIFY // +//--------------------------------------------------------------------------------------// + #undef BOOST_VERIFY #if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) ) From 3279399fe32f2ecc5bdd3b80c5792212e308d797 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 24 Jan 2011 20:15:36 +0000 Subject: [PATCH 07/19] Remove BOOST_ENABLE_ASSERT_MSG_HANDLER; use BOOST_ENABLE_ASSERT_HANDLER in its stead [SVN r68423] --- assert.html | 4 ++-- assert_test.cpp | 1 - include/boost/assert.hpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/assert.html b/assert.html index aa3cbf2..5f3f6e7 100644 --- a/assert.html +++ b/assert.html @@ -66,7 +66,7 @@

BOOST_ASSERT_MSG(expr, msg) is equivalent to ((void)0) if BOOST_DISABLE_ASSERTS or NDEBUG are defined or expr evaluates to true. If those - macros and BOOST_ENABLE_ASSERT_MSG_HANDLER are not + macros and BOOST_ENABLE_ASSERT_HANDLER are not defined, and expr evaluates to false, an error message that includes #expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, and __LINE__ is sent to output stream @@ -77,7 +77,7 @@ may produce easier to understand output if messages go to a different stream, such as std::cout. Users may define BOOST_ASSERT_MSG_OSTREAM before including <boost/assert.hpp> to specify a different output stream. 

-

If the macro BOOST_ENABLE_ASSERT_MSG_HANDLER is defined when <boost/assert.hpp> +

If the macro BOOST_ENABLE_ASSERT_HANDLER is defined when <boost/assert.hpp> is included, instead of sending a error message to an output stream, this expression is evaluated

diff --git a/assert_test.cpp b/assert_test.cpp index a0e1e04..26051ac 100644 --- a/assert_test.cpp +++ b/assert_test.cpp @@ -66,7 +66,6 @@ void test_disabled() #undef BOOST_DISABLE_ASSERTS #define BOOST_ENABLE_ASSERT_HANDLER -#define BOOST_ENABLE_ASSERT_MSG_HANDLER #include #include #include diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index a04e2e4..174f084 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -61,7 +61,7 @@ namespace boost #define BOOST_ASSERT_MSG(expr, msg) ((void)0) -#elif defined(BOOST_ENABLE_ASSERT_MSG_HANDLER) +#elif defined(BOOST_ENABLE_ASSERT_HANDLER) #include From 7d23c75eefb4597f66fd34c31be2740ffa25a2a6 Mon Sep 17 00:00:00 2001 From: David Deakins Date: Fri, 18 Feb 2011 03:46:55 +0000 Subject: [PATCH 08/19] Revised the assertion_failed_msg function to use std::exit(-1) instead of std::abort() for Windows CE (since Windows CE does not have an abort() function in the CRT library) [SVN r68982] --- include/boost/assert.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index 174f084..a233505 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -101,7 +101,12 @@ namespace boost << "***** Internal Program Error - assertion (" << expr << ") failed in " << function << ":\n" << file << '(' << line << "): " << msg << std::endl; - std::abort(); + #ifdef UNDER_CE + // The Windows CE CRT library does not have abort() so use exit(-1) instead. + std::exit(-1); + #else + std::abort(); + #endif } } // detail } // assertion From 95d2c38379cc6add757ef75a53dfe7d71dbfbf02 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Wed, 6 Apr 2011 20:21:51 +0000 Subject: [PATCH 09/19] Fix doc errors reported by Rob Stewart. Fixes #5421. [SVN r71047] --- doc/declval.qbk | 6 +++--- doc/html/declval.html | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/declval.qbk b/doc/declval.qbk index 67e82d2..8b59178 100644 --- a/doc/declval.qbk +++ b/doc/declval.qbk @@ -59,9 +59,9 @@ T is an lvalue-reference, otherwise an rvalue. To extend the domain of this func typename std::add_rvalue_reference::type declval(); // not used which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()` -already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C==0x standard. +already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard. -The provision of a new library component that allows the production of values in unevaluated expressions is considered as +The provision of a new library component that allows the production of values in unevaluated expressions is considered important to realize constrained templates in C++0x where concepts are not available. This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer. @@ -96,7 +96,7 @@ The library provides the function template declval to simplify the definition of template decltype(static_cast(declval())) convert(From&&); -Declares a function template convert which only participats in overloading if the type From can be explicitly converted to type To. +Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To. [endsect] diff --git a/doc/html/declval.html b/doc/html/declval.html index a2c5a01..2810dc4 100644 --- a/doc/html/declval.html +++ b/doc/html/declval.html @@ -3,7 +3,7 @@ Declval - + @@ -17,7 +17,7 @@
-
+

@@ -35,9 +35,9 @@

-
+
-

+

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

@@ -49,10 +49,10 @@

Table of Contents

Overview
-
Reference
+
Reference
-
+
@@ -103,18 +103,18 @@ which ensures that we can also use cv void as template parameter. The careful reader might have noticed that declval() already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in - the C==0x standard. + the C++0x standard.

The provision of a new library component that allows the production of values - in unevaluated expressions is considered as important to realize constrained - templates in C++0x where concepts are not available. This extremely light-weight - function is expected to be part of the daily tool-box of the C++0x programmer. + in unevaluated expressions is considered important to realize constrained templates + in C++0x where concepts are not available. This extremely light-weight function + is expected to be part of the daily tool-box of the C++0x programmer.

-
+

#include <boost/utility/declval.hpp> @@ -148,13 +148,13 @@ decltype(static_cast<To>(declval<From>())) convert(From&&);

- Declares a function template convert which only participats in overloading + Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.

- +

Last revised: September 16, 2010 at 16:19:10 GMT

Last revised: April 06, 2011 at 20:06:10 GMT


From 5684a2f2b3b43f297eee59e90a0f0621c0a4bb0e Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 13 Apr 2011 02:30:39 +0000 Subject: [PATCH 10/19] Applied doc patches from Matt Calabrese [SVN r71221] --- enable_if.html | 111 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 18 deletions(-) diff --git a/enable_if.html b/enable_if.html index a17a290..8ea33bb 100644 --- a/enable_if.html +++ b/enable_if.html @@ -21,6 +21,7 @@

Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.
+Copyright 2011 Matt Calabrese.

@@ -81,7 +82,7 @@ definitions to find this out. Instantiating the latter definition with
int::result_type negate(const int&);
 
 
-where the return type is invalid. If this was an error, adding an unrelated function template +where the return type is invalid. If this were an error, adding an unrelated function template (that was never called) could break otherwise valid code. Due to the SFINAE principle the above example is not, however, erroneous. The latter definition of negate is simply removed from the overload resolution set.
@@ -154,6 +155,7 @@ typename enable_if<boost::is_arithmetic<T>, T>::type foo(T t) { return t; } +

3  Using enable_if

@@ -162,8 +164,19 @@ foo(T t) { return t; } The enable_if templates are defined in boost/utility/enable_if.hpp, which is included by boost/utility.hpp.

-The enable_if template can be used either as the return type, or as an -extra argument. For example, the foo function in the previous section could also be written +With respect to function templates, enable_if can be used in multiple different ways: + +
    +
  • As the return type of an instantiatied function +
  • As an extra parameter of an instantiated function +
  • As an extra template parameter (useful only in a compiler that supports C++0x default +arguments for function template parameters, see Enabling function +templates in C++0x for details) +
+ +In the previous section, the return type form of enable_if was shown. As an example +of using the form of enable_if that works via an extra function parameter, the +foo function in the previous section could also be written as:
template <class T>
 T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0); 
@@ -173,18 +186,80 @@ a default value to keep the parameter hidden from client code.
 Note that the second template argument was not given to enable_if, as the default 
 void gives the desired behavior.

-Whether to write the enabler as an argument or within the return type is -largely a matter of taste, but for certain functions, only one -alternative is possible: +Which way to write the enabler is largely a matter of taste, but for certain functions, only a +subset of the options is possible:
  • -Operators have a fixed number of arguments, thus enable_if must be used in the return type. -
  • Constructors and destructors do not have a return type; an extra argument is the only option. -
  • There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors, -however, can have enablers as extra default arguments. +Many operators have a fixed number of arguments, thus enable_if must be used either in the +return type or in an extra template parameter. +
  • Functions that have a variadic parameter list must use either the return type form or an extra +template parameter. +
  • Constructors do not have a return type so you must use either an extra function parameter or an +extra template parameter. +
  • Constructors that have a variadic parameter list must an extra template parameter. +
  • Conversion operators can only be written with an extra template parameter.
+ + + +

3.1  Enabling function templates in C++0x

+ +In a compiler which supports C++0x default arguments for function template parameters, you can +enable and disable function templates by adding an additional template parameter. This approach +works in all situations where you would use either the return type form of enable_if or +the function parameter form, including operators, constructors, variadic function templates, and +even overloaded conversion operations. + +As an example: + +
#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+
+class test
+{
+public:
+  // A constructor that works for any argument list of size 10
+  template< class... T
+          , typename boost::enable_if_c< sizeof...( T ) == 10, int >::type = 0
+          >
+  test( T&&... );
+
+  // A conversion operation that can convert to any arithmetic type
+  template< class T
+          , typename boost::enable_if< boost::is_arithmetic< T >, int >::type = 0
+          >
+  operator T() const;
+
+  // A conversion operation that can convert to any pointer type
+  template< class T
+          , typename boost::enable_if< boost::is_pointer< T >, int >::type = 0
+          >
+  operator T() const;
+};
+
+int main()
+{
+  // Works
+  test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
+
+  // Fails as expected
+  test fail_construction( 1, 2, 3, 4, 5 );
+
+  // Works by calling the conversion operator enabled for arithmetic types
+  int arithmetic_object = test_;
+
+  // Works by calling the conversion operator enabled for pointer types
+  int* pointer_object = test_;
+
+  // Fails as expected
+  struct {} fail_conversion = test_;
+}
+
+
+ -

3.1  Enabling template class specializations

+

3.2  Enabling template class specializations

Class template specializations can be enabled or disabled with enable_if. @@ -210,7 +285,7 @@ is the correct value.

-

3.2  Overlapping enabler conditions

+

3.3  Overlapping enabler conditions

Once the compiler has examined the enabling conditions and included the @@ -239,7 +314,7 @@ partial specializations as well.

-

3.3  Lazy enable_if

+

3.4  Lazy enable_if

In some cases it is necessary to avoid instantiating part of a @@ -285,7 +360,7 @@ above example, is_multipliable<T, U>::value defines when
-

3.4  Compiler workarounds

+

3.5  Compiler workarounds

Some compilers flag functions as ambiguous if the only distinguishing factor is a different @@ -367,9 +442,9 @@ David Vandevoorde and Nicolai M. Josuttis. Addison-Wesley, 2002.
-

Copyright Jaakko Järvi, Jeremiah Willcock and Andrew Lumsdaine
-{jajarvi|jewillco|lums}@osl.iu.edu
-Indiana University
+

Copyright Jaakko Järvi*, Jeremiah Willcock*, Andrew Lumsdaine*, Matt Calabrese
+{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com
+*Indiana University
Open Systems Lab
Use, modification and distribution are subject to the Boost Software License, Version 1.0. @@ -386,4 +461,4 @@ or copy at HEVEA. - \ No newline at end of file + From 1d146d010a72040eafedba6c4f97954cb7ba2371 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 6 May 2011 19:55:35 +0000 Subject: [PATCH 11/19] upped BOOST_RESULT_OF_NUM_ARGS for Phoenix [SVN r71769] --- include/boost/utility/result_of.hpp | 2 +- utility.htm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 41cc176..77c26fe 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -27,7 +27,7 @@ #include #ifndef BOOST_RESULT_OF_NUM_ARGS -# define BOOST_RESULT_OF_NUM_ARGS 10 +# define BOOST_RESULT_OF_NUM_ARGS 16 #endif namespace boost { diff --git a/utility.htm b/utility.htm index 3ac5d42..b9707db 100644 --- a/utility.htm +++ b/utility.htm @@ -155,7 +155,7 @@ void f() { the type F to be a function pointer, function reference, member function pointer, or class type. By default, N may be any value between 0 and - 10. To change the upper limit, define the macro + 16. To change the upper limit, define the macro BOOST_RESULT_OF_NUM_ARGS to the maximum value for N. Class template result_of resides in the header < Date: Wed, 1 Jun 2011 19:29:57 +0000 Subject: [PATCH 12/19] updated result_of doc with decltype info [SVN r72336] --- utility.htm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/utility.htm b/utility.htm index b9707db..bca0e52 100644 --- a/utility.htm +++ b/utility.htm @@ -224,6 +224,15 @@ typedef boost::result_of< >::type type;

+

In a future + release, BOOST_RESULT_OF_USE_DECLTYPE + may be enabled by default on compilers that + support decltype, so if you use the above + protocol please take care to ensure that + the result_type + and result<> members are + accurate.

+

This implementation of result_of requires class template partial specialization, the From 6d196c4244b69a09e10f586e19418275dddb1550 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Wed, 1 Jun 2011 20:02:40 +0000 Subject: [PATCH 13/19] added tr1_result_of info to result_of doc [SVN r72337] --- utility.htm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utility.htm b/utility.htm index bca0e52..5108060 100644 --- a/utility.htm +++ b/utility.htm @@ -231,7 +231,11 @@ typedef boost::result_of< protocol please take care to ensure that the result_type and result<> members are - accurate.

+ accurate. If you wish to continue to use the protocol + on compilers that support decltype, + use boost::tr1_result_of, which is + also defined + in <boost/utility/result_of.hpp>.

This implementation of result_of From 9525d062b36ab11b5bee4d684810cba7f06ce1e3 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 3 Jun 2011 14:45:59 +0000 Subject: [PATCH 14/19] added clarification to result_of doc [SVN r72377] --- utility.htm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/utility.htm b/utility.htm index 5108060..474a338 100644 --- a/utility.htm +++ b/utility.htm @@ -230,11 +230,12 @@ typedef boost::result_of< support decltype, so if you use the above protocol please take care to ensure that the result_type - and result<> members are - accurate. If you wish to continue to use the protocol - on compilers that support decltype, - use boost::tr1_result_of, which is - also defined + and result<> members accurately + represent the result type. If you wish to continue to + use the protocol on compilers that + support decltype, + use boost::tr1_result_of, which is also + defined in <boost/utility/result_of.hpp>.

From 26b39384e36c2ce4cf8232f66d9fe0677fbb03c3 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 14 Jun 2011 08:27:14 +0000 Subject: [PATCH 15/19] Apply patch from #5607. Refs #5607. [SVN r72580] --- include/boost/current_function.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp index aa5756e..cb36e35 100644 --- a/include/boost/current_function.hpp +++ b/include/boost/current_function.hpp @@ -28,7 +28,7 @@ namespace detail inline void current_function_helper() { -#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) # define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ @@ -65,3 +65,4 @@ inline void current_function_helper() } // namespace boost #endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED + From fe653d0a9ae5f27fb8eca77d944aa44a5cc637b0 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sat, 20 Aug 2011 16:03:58 +0000 Subject: [PATCH 16/19] Change call_traits to pass enum's by value. Fixes #5790. [SVN r73953] --- call_traits_test.cpp | 8 +++++++- include/boost/detail/call_traits.hpp | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/call_traits_test.cpp b/call_traits_test.cpp index 72852c4..9e49b68 100644 --- a/call_traits_test.cpp +++ b/call_traits_test.cpp @@ -210,8 +210,10 @@ int main() comparible_UDT u; c1(u); call_traits_checker c2; + call_traits_checker c2b; int i = 2; c2(i); + c2b(one); int* pi = &i; int a[2] = {1,2}; #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) @@ -292,7 +294,11 @@ int main() BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits::reference); BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::const_reference); BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::param_type); - + // test enum: + BOOST_CHECK_TYPE(enum_UDT, boost::call_traits::value_type); + BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits::param_type); return 0; } diff --git a/include/boost/detail/call_traits.hpp b/include/boost/detail/call_traits.hpp index 6ad646e..36dea00 100644 --- a/include/boost/detail/call_traits.hpp +++ b/include/boost/detail/call_traits.hpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -43,20 +44,26 @@ struct ct_imp2 typedef const T param_type; }; -template +template struct ct_imp { typedef const T& param_type; }; -template -struct ct_imp +template +struct ct_imp { typedef typename ct_imp2::param_type param_type; }; -template -struct ct_imp +template +struct ct_imp +{ + typedef typename ct_imp2::param_type param_type; +}; + +template +struct ct_imp { typedef const T param_type; }; @@ -79,7 +86,8 @@ public: typedef typename boost::detail::ct_imp< T, ::boost::is_pointer::value, - ::boost::is_arithmetic::value + ::boost::is_arithmetic::value, + ::boost::is_enum::value >::param_type param_type; }; From e763315b55ad2afdfee5712ba1ef417a571a0ec8 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Sat, 11 Feb 2012 18:27:02 +0000 Subject: [PATCH 17/19] Updated boost::base_from_member for C++2011. [SVN r76982] --- base_from_member.html | 51 ++++++++++++++++------ include/boost/utility/base_from_member.hpp | 12 ++++- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/base_from_member.html b/base_from_member.html index 21ee6d2..df4add2 100644 --- a/base_from_member.html +++ b/base_from_member.html @@ -129,6 +129,8 @@ particular member type does not need to concern itself with the integer.

Synopsis

+#include <type_traits>  // exposition only
+
 #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
 #define BOOST_BASE_FROM_MEMBER_MAX_ARITY  10
 #endif
@@ -139,6 +141,11 @@ class boost::base_from_member
 protected:
     MemberType  member;
 
+#if C++2011 is in use
+    template< typename ...T >
+    explicit constexpr   base_from_member( T&& ...x )
+     noexcept( std::is_nothrow_constructible<MemberType, T...>::value );
+#else
     base_from_member();
 
     template< typename T1 >
@@ -154,6 +161,7 @@ protected:
      typename T10 >
     base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
      T8 x8, T9 x9, T10 x10 );
+#endif
 };
 
@@ -166,13 +174,27 @@ value of zero if it is omitted. The class template has a protected data member called member that the derived class can use for later base classes (or itself).

-

There is a default constructor and several constructor member -templates. These constructor templates can take as many arguments -(currently up to ten) as possible and pass them to a constructor of -the data member. Since C++ does not allow any way to explicitly state +

If the variadic template arguments and r-value reference features of C++2011 +are present, there will be a single constructor template. It implements +"perfect forwarding" to the best constructor call of +member (if any). The constructor template is marked both +constexpr and explicit. The former will be ignored +if the corresponding inner constructor call (of member) does not +have the marker. The latter binds the other way; always taking effect, even +when the inner constructor call does not have the marker. The constructor +template propagates the noexcept status of the inner constructor +call.

+ +

On earlier-standard compilers, there is a default constructor and several +constructor member templates. These constructor templates can take as many +arguments (currently up to ten) as possible and pass them to a constructor of +the data member.

+ +

Since C++ does not allow any way to explicitly state the template parameters of a templated constructor, make sure that the arguments are already close as possible to the actual type used in -the data member's desired constructor.

+the data member's desired constructor. Explicit conversions may be +necessary.

The BOOST_BASE_FROM_MEMBER_MAX_ARITY macro constant specifies the maximum argument length for the constructor templates. The constant @@ -180,7 +202,7 @@ may be overridden if more (or less) argument configurations are needed. The constant may be read for code that is expandable like the class template and needs to maintain the same maximum size. (Example code would be a class that uses this class template as a base class for a member with a flexible set of -constructors.)

+constructors.) This constant is ignored when C++2011 features are present.

Usage

@@ -323,11 +345,14 @@ constructor argument for pbase0_type is converted from argument for pbase2_type is converted from int to double. The second constructor argument for pbase3_type is a special case of necessary conversion; all -forms of the null-pointer literal in C++ also look like compile-time -integral expressions, so C++ always interprets such code as an integer -when it has overloads that can take either an integer or a pointer. The -last conversion is necessary for the compiler to call a constructor form -with the exact pointer type used in switcher's constructor.

+forms of the null-pointer literal in C++ (except nullptr from +C++2011) also look like compile-time integral expressions, so C++ always +interprets such code as an integer when it has overloads that can take either +an integer or a pointer. The last conversion is necessary for the compiler to +call a constructor form with the exact pointer type used in +switcher's constructor. (If C++2011's nullptr is +used, it still needs a conversion if multiple pointer types can be accepted in +a constructor call but std::nullptr_t cannot.)

Credits

@@ -360,9 +385,9 @@ with the exact pointer type used in switcher's constructor.


-

Revised: 28 August 2004

+

Revised: 11 February 2012

-

Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution +

Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp index 04aabb5..8148077 100644 --- a/include/boost/utility/base_from_member.hpp +++ b/include/boost/utility/base_from_member.hpp @@ -1,6 +1,6 @@ // boost utility/base_from_member.hpp header file --------------------------// -// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and +// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and // distribution are subject to the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or a copy at // .) @@ -10,6 +10,7 @@ #ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP #define BOOST_UTILITY_BASE_FROM_MEMBER_HPP +#include #include #include #include @@ -68,12 +69,21 @@ class base_from_member protected: MemberType member; +#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) + template + explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) + BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType( + static_cast(x)... )) ) // no std::is_nothrow_constructible... + : member( static_cast(x)... ) // ...nor std::forward needed + {} +#else base_from_member() : member() {} BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY), BOOST_PRIVATE_CTR_DEF, _ ) +#endif }; // boost::base_from_member From 9a16aaa2b9ebef80131a6ae5f342320393933cd6 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Wed, 15 Feb 2012 00:41:33 +0000 Subject: [PATCH 18/19] Added LocalFunction and Utility/IdentityType source files. [SVN r77024] --- include/boost/utility/identity_type.hpp | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 include/boost/utility/identity_type.hpp diff --git a/include/boost/utility/identity_type.hpp b/include/boost/utility/identity_type.hpp new file mode 100644 index 0000000..c297c49 --- /dev/null +++ b/include/boost/utility/identity_type.hpp @@ -0,0 +1,45 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +/** @file +Wrap type expressions with round parenthesis so they can be passed to macros +even if they contain commas. +*/ + +#ifndef BOOST_IDENTITY_TYPE_HPP_ +#define BOOST_IDENTITY_TYPE_HPP_ + +#include + +/** +@brief This macro allows to wrap the specified type expression within extra +round parenthesis so the type can be passed as a single macro parameter even if +it contains commas (not already wrapped within round parenthesis). + +@Params +@Param{parenthesized_type, +The type expression to be passed as macro parameter wrapped by a single set +of round parenthesis (...). +This type expression can contain an arbitrary number of commas. +} +@EndParams + +This macro works on any C++03 compiler (it does not require variadic macros). + +This macro must be prefixed by typename when used within templates. +However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to +be explicitly specified when calling the function template). + +On some compilers (like GCC), using this macro on an abstract types requires to +add and remove a reference to the type. +*/ +#define BOOST_IDENTITY_TYPE(parenthesized_type) \ + /* must NOT prefix this with `::` to work with parenthesized syntax */ \ + boost::function_traits< void parenthesized_type >::arg1_type + +#endif // #include guard + From ef0f82f62b8404382ed2ae8a5d338d85f221501a Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Wed, 15 Feb 2012 01:16:00 +0000 Subject: [PATCH 19/19] Added Utility/IdentityType docs, tests, and examples to libs/. [SVN r77029] --- identity_type/doc/Jamfile.v2 | 31 ++++ identity_type/doc/html/index.html | 228 ++++++++++++++++++++++++++++ identity_type/doc/identity_type.qbk | 159 +++++++++++++++++++ identity_type/index.html | 15 ++ identity_type/test/Jamfile.v2 | 14 ++ identity_type/test/template.cpp | 48 ++++++ identity_type/test/tmp_assert.cpp | 51 +++++++ identity_type/test/var.cpp | 26 ++++ identity_type/test/var_err.cpp | 18 +++ 9 files changed, 590 insertions(+) create mode 100644 identity_type/doc/Jamfile.v2 create mode 100644 identity_type/doc/html/index.html create mode 100644 identity_type/doc/identity_type.qbk create mode 100644 identity_type/index.html create mode 100644 identity_type/test/Jamfile.v2 create mode 100644 identity_type/test/template.cpp create mode 100644 identity_type/test/tmp_assert.cpp create mode 100644 identity_type/test/var.cpp create mode 100644 identity_type/test/var_err.cpp diff --git a/identity_type/doc/Jamfile.v2 b/identity_type/doc/Jamfile.v2 new file mode 100644 index 0000000..29ea0a9 --- /dev/null +++ b/identity_type/doc/Jamfile.v2 @@ -0,0 +1,31 @@ + +# Copyright (C) 2009-2012 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 +# (see accompanying file LICENSE_1_0.txt or a copy at +# http://www.boost.org/LICENSE_1_0.txt) +# Home at http://www.boost.org/libs/utility/identity_type + +import quickbook ; +using boostbook ; + +doxygen reference : ../../../../boost/utility/identity_type.hpp + : "Reference" + PREDEFINED="DOXYGEN" + QUIET=YES + WARN_IF_UNDOCUMENTED=NO + HIDE_UNDOC_MEMBERS=YES + HIDE_UNDOC_CLASSES=YES + ALIASES=" Params=\"Parameters: \" Param{2}=\"\" EndParams=\"
\\1\\2
\" Returns=\"Returns:\" Note=\"Note:\" Warning=\"Warning:\" See=\"See:\" RefSect{1}=\"\\xmlonly\\1\\endxmlonly\" RefSectId{2}=\"\\xmlonly\\2\\endxmlonly\" RefClass{1}=\"\\xmlonly\\1\\endxmlonly\" RefFunc{1}=\"\\xmlonly\\1\\endxmlonly\" RefMacro{1}=\"\\xmlonly\\1\\endxmlonly\" " + ; + +# This target must be called "index" so to generate "index.html" file. +xml index : identity_type.qbk : reference ; + +boostbook doc : index + : html + onehtml + toc.section.depth=0 + html.stylesheet=../../../../../doc/src/boostbook.css + boost.root=../../../../.. + ; + diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html new file mode 100644 index 0000000..c0dc1ee --- /dev/null +++ b/identity_type/doc/html/index.html @@ -0,0 +1,228 @@ +Boost.Utility/IdentityType 1.0.0

Boost.Utility/IdentityType 1.0.0

Lorenzo Caminiti

+ Distributed under the Boost Software License, Version 1.0 (see accompanying + file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt) +

+ This library allows to wrap type expressions within round parenthesis so they + can be passed to macros even when they contain commas. +

+ Consider the following macro which declares a variable named varn with the specified + type (see also var_err.cpp): +

+

#define VAR(type, n) type var ## n
+
+VAR( int, 1 );                  // OK.
+VAR( std::map<int, char>, 2 );  // Error.
+

+

+ The first macro invocation works correctly declaring a variable named var1 of type int. + However, the second macro invocation fails generating a preprocessor error + similar to the following: +

error: macro "VAR" passed 3 arguments, but takes just 2
+

+ That is because the std::map type passed as the first macro parameter + contains a comma , not wrapped + by round parenthesis (). The preprocessor + interprets that unwrapped comma as a separation between macro parameters concluding + that a total of three (and not two) parameters are passed to the macro in the + following order: +

  1. + std::map<int +
  2. + char> +
  3. + 2 +

+ Note that, differently from the compiler, the preprocessor only recognizes + round parameters (). Angular + <> or squared [] parenthesis are not used by the preprocessor + when parsing the macro parameters. +

+ In some cases, it might be possible to workaround this issue by avoiding to + pass the type expression to the macro all together. For example, in some cases + a typedef can be used to specify + the type expression with the commas outside the macro (see also var.cpp): +

+

typedef std::map<int, char> map_type;
+VAR( map_type, 3 ); // OK.
+

+

+ When this is not possible or desired (e.g., see the function template f in the section below), the library header + boost/utility/identity_type.hpp + defines a macro BOOST_IDENTITY_TYPE + which can be used to workaround the issue while keeping the type expression + as one of the macro parameters (see also var.cpp). +

+

#include <boost/utility/identity_type.hpp>
+
+VAR( BOOST_IDENTITY_TYPE((std::map<int, char>)), 4 ); // OK.
+

+

+ This macro expands to an expression that evaluates (at compile-time) to the + specified type. The specified type is never split into multiple macro parameters + because it is always wrapped by a set of extra round parenthesis (). In fact, a total of two sets of round parenthesis + must be used: The parenthesis to invoke the macro BOOST_IDENTITY_TYPE(...) plus the inner parenthesis to wrap the + type passed to the macro BOOST_IDENTITY_TYPE((...)). +

+ This macro works on any C++03 + compiler (because it does not use variadic + macros). [1] +

+ This macro must be prefixed by typename + when used within templates. For example, let's program a macro that declares + a function parameter named argn + with the specified type (see also template.cpp): +

+

#define ARG(type, n) type arg ## n
+
+template<typename T>
+void f( // Prefix macro with `typename` in templates.
+    ARG( typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1 )
+) {
+    std::cout << arg1[0] << std::endl;
+}
+

+

+

std::map<int, char> a;
+a[0] = 'a';
+
+f<char>(a); // OK.
+// f(a);    // But error.
+

+

+ However, note that the template parameter type char + must be explicitly specified when invoking the function f<char>(a). In fact, + when the BOOST_IDENTITY_TYPE + macro is used to wrap a function template parameter, the template parameter + can no longer be implicitly determined by the compiler form the function call + as in f(a). (This + limitation does not apply to class templates because class template parameters + must always be explicitly specified.) In other words, without using the BOOST_IDENTITY_TYPE macro, C++ would + normally be able to implicitly deduce the function template parameter as shown + below: +

+

template<typename T>
+void g(
+    std::map<int, T> arg1
+) {
+    std::cout << arg1[0] << std::endl;
+}
+

+

+

g<char>(a); // OK.
+g(a);       // Also OK.
+

+

+ On some compilers (e.g., GCC), using this macro on abstract types (i.e., a + class with one or more pure virtual functions) generates a compiler error. + This can be worked around by manipulating the type adding and removing a reference + to it. +

+ Let's program a macro that performs a static assertion on a Template + Meta-Programming (TMP) meta-function (similarly to Boost.MPL BOOST_MPL_ASSERT). The BOOST_IDENTITY_TYPE macro can be used + to pass a meta-function with multiple template parameters to the assert macro + (so to handle the commas separating the template parameters). In this case, + if the meta-function is an abstract type, it needs to be manipulated adding + and removing a reference to it (see also tmp_assert.cpp): +

+

#define TMP_ASSERT(metafunction) \
+    BOOST_STATIC_ASSERT(metafunction::value)
+
+template<typename T, bool b>
+struct abstract {
+    static const bool value = b;
+    virtual void f(T const& x) = 0;
+};
+
+TMP_ASSERT(
+    boost::remove_reference<            // Add and remove
+        BOOST_IDENTITY_TYPE((           // reference for
+            boost::add_reference<       // abstract type.
+                abstract<int, true>
+            >::type
+        ))
+    >::type
+);
+

+

+ The BOOST_IDENTITY_TYPE macro + can be used either in the call of the user-defined macro (as shown by the examples + so far), or internally to the definition of the user macro. When BOOST_IDENTITY_TYPE is used internally, + the call of the user macro will only have to specify the extra parenthesis + (see also tmp_assert.cpp): +

+

#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
+    /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
+    BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
+
+TMP_ASSERT_PAREN(( boost::is_const<std::map<int, char> const> ));
+TMP_ASSERT( BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)) );
+

+

+ However, note that the user will always have to specify + the extra parenthesis even when the macro parameters contain no comma: +

+

TMP_ASSERT_PAREN(( boost::is_const<int const> )); // Always extra `()`.
+TMP_ASSERT( boost::is_const<int const> ); // No extra `()` and no macro.
+

+

+ In some cases, using BOOST_IDENTITY_TYPE + internally might provide the best syntax for the user. For example, this is + the case for BOOST_MPL_ASSERT + because the majority of template meta-programming expressions contain unwrapped + commas so it is less confusing for the user to always specify the extra parenthesis + ((...)) instead of using BOOST_IDENTITY_TYPE: +

BOOST_MPL_ASSERT(( // Natural syntax.
+    boost::mpl::and_<
+          boost::is_const<T>
+        , boost::is_reference<T>
+    >
+));
+

+ However, in other situations it might be preferable to not require the extra + parenthesis in common cases and handle commas as special cases using the BOOST_IDENTITY_TYPE. For example, this + is the case for BOOST_LOCAL_FUNCTION + for which always requiring the extra parenthesis ((...)) + around the types would lead to an unnatural syntax for the local function parameter + types: +

int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
+    return x + y;
+} BOOST_LOCAL_FUNCTION_NAME(add)
+

+ Instead requiring the user to specify BOOST_IDENTITY_TYPE + when needed allows for the more natural syntax BOOST_LOCAL_FUNCTION(int& + x, int& y) in the common cases when the parameter types + contain no comma. +

+ The implementation of this library macro is equivalent to the following: [2] +

#include <boost/type_traits/function_traits.hpp>
+
+#define BOOST_IDENTITY_TYPE(parenthesized_type) \
+    boost::function_traits<void parenthesized_type>::arg1_type
+

+ Essentially, the type is wrapped between round parenthesis (std::map<int, + char>) + so it can be passed as a macro parameter even if it contain commas. Then the + parenthesized type is transformed into the type of a function returning void and with the specified type as the type + of the first and only argument void + (std::map<int, char>). Finally, the type of the first argument + arg1_type is extracted therefore + obtaining the original type from the parenthesized type (effectively stripping + the parenthesis from around the type). +

Reference

Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas.

+
+BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
+
+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+

This macro works on any C++03 compiler (it does not require variadic macros).

This macro must be prefixed by typename when used within templates. However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on an abstract types requires to add and remove a reference to the type.



[1] + Using variadic macros, it would be possible to use a single set of parenthesis + BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) + but variadic macros are not part of C++03 (even if nowadays they are supported + by most modern compilers and they are also part of C++11). +

[2] + There is absolutely no guarantee that the macro is actually implemented using + the code listed in this documentation. This code is for explanatory purposes + only. +

diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk new file mode 100644 index 0000000..d5107a3 --- /dev/null +++ b/identity_type/doc/identity_type.qbk @@ -0,0 +1,159 @@ + +[/ Copyright (C) 2009-2012 Lorenzo Caminiti ] +[/ Distributed under the Boost Software License, Version 1.0 ] +[/ (see accompanying file LICENSE_1_0.txt or a copy at ] +[/ http://www.boost.org/LICENSE_1_0.txt) ] +[/ Home at http://www.boost.org/libs/utility/identity_type ] + +[library Boost.Utility/IdentityType + [quickbook 1.5] + [version 1.0.0] + [copyright 2009-2012 Lorenzo Caminiti] + [purpose wraps types with round parenthesis] + [license + Distributed under the Boost Software License, Version 1.0 + (see accompanying file LICENSE_1_0.txt or a copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Caminiti lorcaminiti@gmail.com, Lorenzo]] + [category Utilities] +] + +This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas. + +[import ../test/var_err.cpp] +[import ../test/var.cpp] +[import ../test/template.cpp] +[import ../test/tmp_assert.cpp] + +[section Motivation] + +Consider the following macro which declares a variable named `var`/n/ with the specified /type/ (see also [@../../test/var_err.cpp =var_err.cpp=]): + +[var_err] + +The first macro invocation works correctly declaring a variable named `var1` of type `int`. +However, the second macro invocation fails generating a preprocessor error similar to the following: + +[pre + error: macro "VAR" passed 3 arguments, but takes just 2 +] + +That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`. +The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order: + +# `std::map` +# `2` + +Note that, differently from the compiler, the preprocessor only recognizes round parameters `()`. +Angular `<>` or squared `[]` parenthesis are not used by the preprocessor when parsing the macro parameters. + +[endsect] + +[section Solution] + +In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together. +For example, in some cases a `typedef` can be used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]): + +[var_typedef] + +When this is not possible or desired (e.g., see the function template `f` in the section below), the library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]). + +[var_ok] + +This macro expands to an expression that evaluates (at compile-time) to the specified type. +The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`. +In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`. + +This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (because it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]). +[footnote +Using variadic macros, it would be possible to use a single set of parenthesis `BOOST_IDENTITY_TYPE(`/type/`)` instead of two `BOOST_IDENTITY_TYPE((`/type/`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11). +] + +[endsect] + +[section Templates] + +This macro must be prefixed by `typename` when used within templates. +For example, let's program a macro that declares a function parameter named `arg`/n/ with the specified /type/ (see also [@../../test/template.cpp =template.cpp=]): + +[template_f_decl] +[template_f_call] + +However, note that the template parameter type `char` must be explicitly specified when invoking the function `f(a)`. +In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be implicitly determined by the compiler form the function call as in `f(a)`. +(This limitation does not apply to class templates because class template parameters must always be explicitly specified.) +In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to implicitly deduce the function template parameter as shown below: + +[template_g_decl] +[template_g_call] + +[endsect] + +[section Abstract Types] + +On some compilers (e.g., GCC), using this macro on abstract types (i.e., a class with one or more pure virtual functions) generates a compiler error. +This can be worked around by manipulating the type adding and removing a reference to it. + +Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]). +The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters). +In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): + +[tmp_assert_abstract] + +[endsect] + +[section Annex: Usage] + +The [macroref BOOST_IDENTITY_TYPE] macro can be used either in the call of the user-defined macro (as shown by the examples so far), or internally to the definition of the user macro. +When [macroref BOOST_IDENTITY_TYPE] is used internally, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): + +[tmp_assert_alternative] + +However, note that the user will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma: + +[tmp_assert_alternative_always] + +In some cases, using [macroref BOOST_IDENTITY_TYPE] internally might provide the best syntax for the user. +For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]: + + BOOST_MPL_ASSERT(( // Natural syntax. + boost::mpl::and_< + boost::is_const + , boost::is_reference + > + )); + +However, in other situations it might be preferable to not require the extra parenthesis in common cases and handle commas as special cases using the [macroref BOOST_IDENTITY_TYPE]. +For example, this is the case for `BOOST_LOCAL_FUNCTION` for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function parameter types: + + int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax. + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + +Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma. + +[endsect] + +[section Annex: Implementation] + +The implementation of this library macro is equivalent to the following: +[footnote +There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation. +This code is for explanatory purposes only. +] + + #include + + #define BOOST_IDENTITY_TYPE(parenthesized_type) \ + boost::function_traits::arg1_type + +Essentially, the type is wrapped between round parenthesis `(std::map)` so it can be passed as a macro parameter even if it contain commas. +Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map)`. +Finally, the type of the first argument `arg1_type` is extracted therefore obtaining the original type from the parenthesized type (effectively stripping the parenthesis from around the type). + +[endsect] + +[xinclude reference.xml] + diff --git a/identity_type/index.html b/identity_type/index.html new file mode 100644 index 0000000..00b3362 --- /dev/null +++ b/identity_type/index.html @@ -0,0 +1,15 @@ + + + + + + + Automatic redirection failed, click this + link  
+

© Copyright Lorenzo Caminiti, 2009-2012

+

Distributed under the Boost Software License, Version 1.0 (see + accompanying file + LICENSE_1_0.txt or a copy at + www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/identity_type/test/Jamfile.v2 b/identity_type/test/Jamfile.v2 new file mode 100644 index 0000000..2f0bdac --- /dev/null +++ b/identity_type/test/Jamfile.v2 @@ -0,0 +1,14 @@ + +# Copyright (C) 2009-2012 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 +# (see accompanying file LICENSE_1_0.txt or a copy at +# http://www.boost.org/LICENSE_1_0.txt) +# Home at http://www.boost.org/libs/utility/identity_type + +import testing ; + +compile-fail var_err.cpp ; +run var.cpp ; +run template.cpp ; +run tmp_assert.cpp ; + diff --git a/identity_type/test/template.cpp b/identity_type/test/template.cpp new file mode 100644 index 0000000..ec42628 --- /dev/null +++ b/identity_type/test/template.cpp @@ -0,0 +1,48 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include + +//[template_f_decl +#define ARG(type, n) type arg ## n + +template +void f( // Prefix macro with `typename` in templates. + ARG( typename BOOST_IDENTITY_TYPE((std::map)), 1 ) +) { + std::cout << arg1[0] << std::endl; +} +//] + +//[template_g_decl +template +void g( + std::map arg1 +) { + std::cout << arg1[0] << std::endl; +} +//] + +int main() { + //[template_f_call + std::map a; + a[0] = 'a'; + + f(a); // OK. + // f(a); // But error. + //] + + //[template_g_call + g(a); // OK. + g(a); // Also OK. + //] + + return 0; +} + diff --git a/identity_type/test/tmp_assert.cpp b/identity_type/test/tmp_assert.cpp new file mode 100644 index 0000000..17755cb --- /dev/null +++ b/identity_type/test/tmp_assert.cpp @@ -0,0 +1,51 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include +#include +#include +#include + +//[tmp_assert_abstract +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template +struct abstract { + static const bool value = b; + virtual void f(T const& x) = 0; +}; + +TMP_ASSERT( + boost::remove_reference< // Add and remove + BOOST_IDENTITY_TYPE(( // reference for + boost::add_reference< // abstract type. + abstract + >::type + )) + >::type +); +//] + +//[tmp_assert_alternative +#define TMP_ASSERT_PAREN(parenthesized_metafunction) \ + /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ + BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) + +TMP_ASSERT_PAREN(( boost::is_const const> )); +TMP_ASSERT( BOOST_IDENTITY_TYPE((boost::is_const const>)) ); +//] + +//[tmp_assert_alternative_always +TMP_ASSERT_PAREN(( boost::is_const )); // Always extra `()`. +TMP_ASSERT( boost::is_const ); // No extra `()` and no macro. +//] + +int main() { return 0; } + diff --git a/identity_type/test/var.cpp b/identity_type/test/var.cpp new file mode 100644 index 0000000..896aa03 --- /dev/null +++ b/identity_type/test/var.cpp @@ -0,0 +1,26 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include + +#define VAR(type, n) type var ## n + +VAR( int, 1 ); // OK. + +//[var_typedef +typedef std::map map_type; +VAR( map_type, 3 ); // OK. +//] + +//[var_ok +#include + +VAR( BOOST_IDENTITY_TYPE((std::map)), 4 ); // OK. +//] + +int main() { return 0; } + diff --git a/identity_type/test/var_err.cpp b/identity_type/test/var_err.cpp new file mode 100644 index 0000000..7ba0c52 --- /dev/null +++ b/identity_type/test/var_err.cpp @@ -0,0 +1,18 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include + +//[var_err +#define VAR(type, n) type var ## n + +VAR( int, 1 ); // OK. +VAR( std::map, 2 ); // Error. +//] + +int main() { return 0; } +