diff --git a/base_from_member.html b/base_from_member.html index 4dd70f4..21ee6d2 100644 --- a/base_from_member.html +++ b/base_from_member.html @@ -334,7 +334,7 @@ with the exact pointer type used in switcher's constructor.

Contributors

-
Ed Brey +
Ed Brey
Suggested some interface changes.
R. Samuel Klatchko (switcher's constructor.

Invented the idiom of how to use a class member for initializing a base class. -
Dietmar Kuehl +
Dietmar Kuehl
Popularized the base-from-member idiom in his IOStream example classes. @@ -353,7 +353,7 @@ with the exact pointer type used in switcher's constructor.

can be controlled and automated with macros. The implementation uses the Preprocessor library. -
Daryle Walker +
Daryle Walker
Started the library. Contributed the test file base_from_member_test.cpp.
diff --git a/generator_iterator.htm b/generator_iterator.htm index c81d3d1..6070522 100644 --- a/generator_iterator.htm +++ b/generator_iterator.htm @@ -153,7 +153,7 @@ int main() 05 December, 2006

Copyright © 2001 Jens Maurer

+ "http://www.boost.org/people/jens_maurer.htm">Jens Maurer

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or diff --git a/include/boost/exception.hpp b/include/boost/exception.hpp new file mode 100644 index 0000000..6a49ab8 --- /dev/null +++ b/include/boost/exception.hpp @@ -0,0 +1,13 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//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) + +#ifndef UUID_1D94A7C6054E11DB9804B622A1EF5492 +#define UUID_1D94A7C6054E11DB9804B622A1EF5492 + +#include +#include +#include + +#endif diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index 097f21a..60879cf 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -1,34 +1,24 @@ -// (C) Copyright 2002-2007, Fernando Luis Cacciola Carballal. +// (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal. // // 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) // // 21 Ago 2002 (Created) Fernando Cacciola -// 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker +// 18 Feb 2008 (Worked around compiler bugs, added initialized_value) Fernando Cacciola, Niels Dekker // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP // Note: The implementation of boost::value_initialized had to deal with the -// fact that various compilers haven't fully implemented value-initialization: -// Microsoft Feedback ID 100744 - Value-initialization in new-expression -// Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005-07-28 -// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 -// GCC Bug 30111 - Value-initialization of POD base class doesn't initialize members -// Reported by Jonathan Wakely, 2006-12-07 -// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 -// GCC Bug 33916 - Default constructor fails to initialize array members -// Reported by Michael Elizabeth Chastain, 2007-10-26 -// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 -// Borland Report 51854 - Value-initialization: POD struct should be zero-initialized -// Reported by Niels Dekker (LKEB, Leiden University Medical Center), 2007-11-09 -// http://qc.codegear.com/wc/qcmain.aspx?d=51854 -// The constructor of boost::value_initialized works around these issues, by -// clearing the bytes of T, before constructing the T object it contains. +// fact that various compilers haven't fully implemented value-initialization. +// The constructor of boost::value_initialized works around these compiler +// issues, by clearing the bytes of T, before constructing the T object it +// contains. More details on these issues are at libs/utility/value_init.htm #include #include +#include #include #include #include @@ -48,23 +38,32 @@ class value_initialized remove_const::type data; }; - mutable aligned_storage::value> x; + mutable +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) + typename +#endif + aligned_storage::value>::type x; + + wrapper * wrapper_address() const + { + return static_cast( static_cast(&x)); + } public : value_initialized() { - std::memset(x.address(), 0, sizeof(x)); + std::memset(&x, 0, sizeof(x)); #ifdef BOOST_MSVC #pragma warning(push) #if _MSC_VER >= 1310 // When using MSVC 7.1 or higher, the following placement new expression may trigger warning C4345: // "behavior change: an object of POD type constructed with an initializer of the form () -// will be default-initialized". There is no need to worry about this, though. +// will be default-initialized". It is safe to ignore this warning when using value_initialized. #pragma warning(disable: 4345) #endif #endif - new (x.address()) wrapper(); + new (wrapper_address()) wrapper(); #ifdef BOOST_MSVC #pragma warning(pop) #endif @@ -72,25 +71,25 @@ class value_initialized value_initialized(value_initialized const & arg) { - new (x.address()) wrapper( *static_cast(arg.x.address()) ); + new (wrapper_address()) wrapper( static_cast(*(arg.wrapper_address()))); } value_initialized & operator=(value_initialized const & arg) { - T & this_data = this->data(); - T const & arg_data = arg.data(); - this_data = arg_data; + // Assignment is only allowed when T is non-const. + BOOST_STATIC_ASSERT( ! is_const::value ); + *wrapper_address() = static_cast(*(arg.wrapper_address())); return *this; } ~value_initialized() { - static_cast(x.address())->wrapper::~wrapper(); + wrapper_address()->wrapper::~wrapper(); } T& data() const { - return static_cast(x.address())->data; + return wrapper_address()->data; } operator T&() const { return this->data(); } @@ -110,6 +109,18 @@ T& get ( value_initialized& x ) return x.data() ; } + +class initialized_value +{ + public : + + template operator T() const + { + return get( value_initialized() ); + } +}; + + } // namespace boost diff --git a/operators.htm b/operators.htm index fca90e5..13d0d0b 100644 --- a/operators.htm +++ b/operators.htm @@ -2029,13 +2029,13 @@ public:

Contributors

-
Dave Abrahams
+
Dave Abrahams
Started the library and contributed the arithmetic operators in boost/operators.hpp.
-
Jeremy Siek
+
Jeremy Siek
Contributed the dereference operators and iterator helpers in iterators_test.cpp.
-
Aleksey +
Aleksey Gurtovoy
Contributed the code to support base class chaining while remaining backward-compatible with old versions of the library.
-
Beman Dawes
+
Beman Dawes
Contributed operators_test.cpp.
-
Daryle Walker
+
Daryle Walker
Contributed classes for the shift operators, equivalence, partial ordering, and arithmetic conversions. Added the grouped operator diff --git a/utility.htm b/utility.htm index 937a8a3..9514188 100644 --- a/utility.htm +++ b/utility.htm @@ -68,7 +68,7 @@ const std::list<T>::iterator next = boost::next(prev, 2);

The distance from the given iterator should be supplied as an absolute value. For example, the iterator four iterators prior to the given iterator p may be obtained by prior(p, 4).

-

Contributed by Dave Abrahams. Two-argument versions by Daniel Walker.

+

Contributed by Dave Abrahams. Two-argument versions by Daniel Walker.

Class noncopyable

Class noncopyable is a base class.  Derive your own class from noncopyable when you want to prohibit copy construction @@ -89,7 +89,7 @@ const std::list<T>::iterator next = boost::next(prev, 2); to verify class noncopyable works as expected. It has have been run successfully under GCC 2.95, Metrowerks CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.

-

Contributed by Dave Abrahams.

+

Contributed by Dave Abrahams.

Example

// inside one of your own headers ...
diff --git a/value_init.htm b/value_init.htm
index 8ceba8b..c97a0eb 100644
--- a/value_init.htm
+++ b/value_init.htm
@@ -17,11 +17,13 @@
 
Rationale
Introduction
+
Details
@@ -30,7 +32,8 @@
Acknowledgements
@@ -44,24 +47,104 @@ for initialization. Depending on the type, the value of a newly constructed object can be zero-initialized (logically 0), default-constructed (using the default constructor), or indeterminate. When writing generic code, -this problem must be addressed. value_initialized provides +this problem must be addressed. The template value_initialized provides a solution with consistent syntax for value initialization of scalar, -union and class types.
+union and class types. +Moreover, value_initialized offers a workaround to various +compiler issues regarding value-initialization. + +Furthermore a convenience class, initialized_value is provided, +to avoid repeating the type name when retrieving the value from a +value_initialized<T> object. +

Introduction

-

The C++ standard [1] contains the definitions +

+There are various ways to initialize a variable, in C++. The following +declarations all may have a local variable initialized to its default +value: +

+  T1 var1;
+  T2 var2 = 0;
+  T3 var3 = {};
+  T4 var4 = T4();
+
+Unfortunately, whether or not any of those declarations correctly +initialize the variable very much depends on its type. The first +declaration is valid for any +DefaultConstructible type (by definition). +However, it does not always do an initialization! +It correctly initializes the variable when it's an instance of a +class, and the author of the class has provided a proper default +constructor. On the other hand, the value of var1 is indeterminate when +its type is an arithmetic type, like int, float, or char. +An arithmetic variable +is of course initialized properly by the second declaration, T2 +var2 = 0. But this initialization form usually won't work for a +class type (unless the class was especially written to support being +initialized that way). The third form, T3 var3 = {} +initializes an aggregate, typically a "C-style" struct or a "C-style" array. +However, the syntax is not allowed for a class that has an explicitly declared +constructor. (But watch out for an upcoming C++ language change, +by Bjarne Stroustrup et al [1]!) +The fourth form is the most generic form of them, as it +can be used to initialize arithmetic types, class types, aggregates, pointers, and +other types. The declaration, T4 var4 = T4(), should be read +as follows: First a temporary object is created, by T4(). +This object is value-initialized. Next the temporary +object is copied to the named variable, var4. Afterwards, the temporary +is destroyed. While the copying and the destruction are likely to +be optimized away, C++ still requires the type T4 to be +CopyConstructible. +(So T4 needs to be both DefaultConstructible and CopyConstructible.) +A class may not be CopyConstructible, for example because it may have a +private and undefined copy constructor, +or because it may be derived from boost::noncopyable. +Scott Meyers [2] explains why a class would be defined like that. +

+

+There is another, less obvious disadvantage to the fourth form, T4 var4 = T4(): +It suffers from various compiler issues, causing +a variable to be left uninitialized in some compiler specific cases. +

+

+The template value_initialized +offers a generic way to initialize +an object, like T4 var4 = T4(), but without requiring its type +to be CopyConstructible. And it offers a workaround to those compiler issues +regarding value-initialization as well! It allows getting an initialized +variable of any type; it only requires the type to be DefaultConstructible. +A properly value-initialized object of type T is +constructed by the following declaration: +

+  value_initialized<T> var;
+
+

+

+The convenience class initialized_value +allows value-initializing a variable as follows: +

+  T var = initialized_value();
+
+This form of initialization is also very similar to T4 var4 = T4(), +but robust against the aforementioned compiler issues. + +

+ +

Details

+

The C++ standard [3] contains the definitions of zero-initialization and default-initialization. Informally, zero-initialization means that the object is given the initial value 0 (converted to the type) and default-initialization means that - POD [2] types are zero-initialized, while class + POD [4] types are zero-initialized, while non-POD class types are initialized with their corresponding default constructors. A declaration can contain an initializer, which specifies the object's initial value. The initializer can be just '()', which states that -the object shall be default-initialized (but see below). However, if a declaration +the object shall be value-initialized (but see below). However, if a declaration has no initializer and it is of a non-const, non-static - POD type, the initial value is indeterminate:(see §8.5 for the + POD type, the initial value is indeterminate: (see §8.5, [dcl.init], for the accurate definitions).

int x ; // no initializer. x value is indeterminate.
std::string s ; // no initializer, s is default-constructed.

int y = int() ;
// y is initialized using copy-initialization
// but the temporary uses an empty set of parentheses as the initializer,
// so it is default-constructed.
// A default constructed POD type is zero-initialized,
// therefore, y == 0.

void foo ( std::string ) ;
foo ( std::string() ) ;
// the temporary string is default constructed
// as indicated by the initializer ()
@@ -87,14 +170,11 @@ the object shall be default-initialized (but see below). However, if a decla

In order to specify value-initialization of an object we need to use the empty-set initializer: ().

-

(but recall that the current C++ Standard states that '()' invokes default-initialization, -not value-initialization)

-

As before, a declaration with no intializer specifies default-initialization, and a declaration with a non-empty initializer specifies copy (=xxx) or direct (xxx) initialization.

-
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialied
+
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialized

value-initialization syntax

@@ -102,7 +182,7 @@ not value-initialization)

parentheses is not permitted by the syntax of initializers because it is parsed as the declaration of a function taking no arguments:

-
int x() ; // declares function int(*)()
int y ( int() ) ; // decalares function int(*)( int(*)() )
+
int x() ; // declares function int(*)()

Thus, the empty () must be put in some other initialization context.

@@ -124,8 +204,50 @@ data member:

template<class T> 
struct W
{
// value-initialization of 'data' here.
W() : data() {}
T data ;
} ;
W<int> w ;
// w.data is value-initialized for any type.
-

This is the solution supplied by the value_initialized<> template - class.

+

This is the solution as it was supplied by earlier versions of the +value_initialized<T> template + class. Unfortunately this approach suffered from various compiler issues.

+ +

compiler issues

+ +Various compilers haven't yet fully implemented value-initialization. +So when an object should be value-initialized (according to the C++ Standard), +it may in practice still be left uninitialized, because of those +compiler issues! It's hard to make a general statement on what those issues +are like, because they depend on the compiler you are using, its version number, +and the type of object you would like to have value-initialized. +Compilers usually support value-initialization for built-in types properly. +But objects of user-defined types that involve aggregates may in some cases +be partially, or even entirely left uninitialized, when they should be value-initialized. +

+

+We have encountered issues regarding value-initialization on compilers by +Microsoft, Sun, Borland, and GNU. Here is a list of bug reports on those issues: + +
+ +Microsoft Feedback ID 100744 - Value-initialization in new-expression +
Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005-07-28 +
+ +GCC Bug 30111 - Value-initialization of POD base class doesn't initialize members +
Reported by Jonathan Wakely, 2006-12-07 +
+ +GCC Bug 33916 - Default constructor fails to initialize array members +
Reported by Michael Elizabeth Chastain, 2007-10-26 +
+ +Borland Report 51854 - Value-initialization: POD struct should be zero-initialized +
Reported by Niels Dekker (LKEB, Leiden University Medical Center), 2007-09-11 +
+
+

+New versions of value_initialized +(Boost release version 1.35 or higher) +offer a workaround to these issues: value_initialized will now clear +its internal data, prior to constructing the object that it contains. +

Types

@@ -189,25 +311,72 @@ wrapped object from within a constant wrapper can be avoided if access to the wrapped object is always performed with the get() idiom:

value_initialized<int> x ;
get(x) = 1 ; // OK

value_initialized<int const> cx ;
get(x) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int> const x_c ;
get(x_c) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int const> const cx_c ;
get(cx_c) = 1 ; // ERROR: Cannot modify a const object
+ +

class initialized_value

+ +
+namespace boost {
+class initialized_value
+{
+  public :
+    template <class T> operator T() const ;
+};
+} // namespace boost
+
+ +The class initialized_value provides a convenient way to get +an initialized value: its conversion operator provides an appropriate +value-initialized object for any CopyConstructible type. + +Suppose you need to have an initialized variable of type T. +You could do it as follows: +
+  T var = T();
+
+But as mentioned before, this form suffers from various compiler issues. +The template value_initialized offers a workaround: +
+  T var = get( value_initialized<T>() );
+
+Unfortunately both forms repeat the type name, which +is rather short now (T), but could of course be +more like Namespace::Template<Arg>::Type. +Instead, one could use initialized_value as follows: +
+  T var = initialized_value();
+

References

- [1] The C++ Standard, ISO/IEC 14882:98
- [2] Plain Old Data + [1] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote + various papers, proposing to extend the support for brace-enclosed initializer lists + in the next version of C++. + This would allow a variable var of any DefaultConstructible type + T to be value-initialized by doing T var = {}. + The papers are listed at Bjarne's web page, + My C++ Standards committee papers
+ [2] Scott Meyers, Effective C++, Third Edition, item 6, + Explicitly disallow the use of compiler-generated functions you do not want, + Scott Meyers: Books and CDs
+ [3] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
+ [4] POD stands for "Plain Old Data" +

Acknowledgements

value_initialized was developed by Fernando Cacciola, with help and suggestions from David Abrahams and Darin Adler.
-Special thanks to Björn Karlsson who carefully edited and completed this documentation. - +Special thanks to Björn Karlsson who carefully edited and completed this documentation. + +

value_initialized was reimplemented by Fernando Cacciola and Niels Dekker +for Boost release version 1.35 (2008), offering a workaround to various compiler issues. +

Developed by Fernando Cacciola, the latest version of this file can be found at www.boost.org, and the boost discussion list -at www.yahoogroups.com/list/boost. + href="http://www.boost.org">www.boost.org.


-

Revised 19 September 2002

+

Revised 16 January 2008

-

© Copyright Fernando Cacciola, 2002.

+

© Copyright Fernando Cacciola, 2002, 2008.

Distributed under the Boost Software License, Version 1.0. See www.boost.org/LICENSE_1_0.txt

diff --git a/value_init_test.cpp b/value_init_test.cpp index 6dc8e27..b7dd956 100644 --- a/value_init_test.cpp +++ b/value_init_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2002, Fernando Luis Cacciola Carballal. +// Copyright 2002-2008, Fernando Luis Cacciola Carballal. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -6,7 +6,8 @@ // // Test program for "boost/utility/value_init.hpp" // -// Initial: 21 Agu 2002 +// 21 Ago 2002 (Created) Fernando Cacciola +// 18 Feb 2008 (Added tests regarding compiler issues and initialized_value) Fernando Cacciola, Niels Dekker #include // For memcmp. #include @@ -51,7 +52,7 @@ struct NonPODBase struct NonPOD : NonPODBase { NonPOD () : id() {} - NonPOD ( std::string const& id_) : id(id_) {} + explicit NonPOD ( std::string const& id_) : id(id_) {} friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod ) { return os << '(' << npod.id << ')' ; } @@ -179,6 +180,32 @@ struct CopyFunctionCallTester }; +template +void check_initialized_value ( T const& y ) +{ + T initializedValue = boost::initialized_value() ; + BOOST_CHECK ( y == initializedValue ) ; +} + +#ifdef __BORLANDC__ +#if __BORLANDC__ == 0x582 +void check_initialized_value( NonPOD const& ) +{ + // The initialized_value check is skipped for Borland 5.82 + // and this type (NonPOD), because the following statement + // won't compile on this particular compiler version: + // NonPOD initializedValue = boost::initialized_value() ; + // + // This is caused by a compiler bug, that is fixed with a newer version + // of the Borland compiler. The Release Notes for Delphi(R) 2007 for + // Win32(R) and C++Builder(R) 2007 (http://dn.codegear.com/article/36575) + // say about similar statements: + // both of these statements now compile but under 5.82 got the error: + // Error E2015: Ambiguity between 'V::V(const A &)' and 'V::V(const V &)' +} +#endif +#endif + // // This test function tests boost::value_initialized for a specific type T. // The first argument (y) is assumed have the value of a value-initialized object. @@ -188,9 +215,13 @@ template bool test ( T const& y, T const& z ) { const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter(); + + check_initialized_value(y); + boost::value_initialized x ; BOOST_CHECK ( y == x ) ; BOOST_CHECK ( y == boost::get(x) ) ; + static_cast(x) = z ; boost::get(x) = z ; BOOST_CHECK ( x == z ) ; @@ -274,6 +305,10 @@ int test_main(int, char **) boost::value_initialized valueInitializedArrayOfBytes; BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0); + boost::value_initialized valueInitializedArrayOfBytes2; + valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes; + BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0); + boost::value_initialized copyFunctionCallTester1; BOOST_CHECK ( ! get(copyFunctionCallTester1).is_copy_constructed); BOOST_CHECK ( ! get(copyFunctionCallTester1).is_assignment_called);