diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index 67127c0..aa7ecb4 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -7,6 +7,7 @@ // 21 Ago 2002 (Created) Fernando Cacciola // 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker // 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola +// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -93,6 +95,11 @@ class value_initialized return wrapper_address()->data; } + void swap(value_initialized & arg) + { + ::boost::swap( this->data(), arg.data() ); + } + operator T&() const { return this->data(); } } ; @@ -110,6 +117,12 @@ T& get ( value_initialized& x ) return x.data() ; } +template +void swap ( value_initialized & lhs, value_initialized & rhs ) +{ + lhs.swap(rhs) ; +} + class initialized_value_t { diff --git a/value_init.htm b/value_init.htm index 531814e..5c1b20e 100644 --- a/value_init.htm +++ b/value_init.htm @@ -253,7 +253,7 @@ its internal data, prior to constructing the object that it contains.

template class value_initialized<T>

-
namespace boost {

template<class T>
class value_initialized
{
public :
value_initialized() : x() {}
operator T&() const { return x ; }
T& data() const { return x ; }

private :
unspecified x ;
} ;

template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}

template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}

} // namespace boost
+
namespace boost {

template<class T>
class value_initialized
{
public :
value_initialized() : x() {}
operator T&() const { return x ; }
T& data() const { return x ; }
void swap( value_initialized<T>& );

private :
unspecified x ;
} ;

template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}

template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}

} // namespace boost

An object of this template class is a T-wrapper convertible to 'T&' whose wrapped object (data member of type T) @@ -276,6 +276,10 @@ non-member function get():

Both const and non-const objects can be wrapped. Mutable objects can be modified directly from within the wrapper but constant objects cannot:

+ +

When T is a Swappable type, value_initialized<T> + is swappable as well, by calling its swap member function + as well as by calling boost::swap.

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

value_initialized<int const> y ;
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
get(y) = 1 ; // ERROR: cannot modify a const value
@@ -311,7 +315,7 @@ 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
- +

initialized_value

@@ -379,7 +383,7 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
      


-

Revised 23 May 2008

+

Revised 28 August 2008

© Copyright Fernando Cacciola, 2002, 2008.

@@ -390,4 +394,4 @@ for Boost release version 1.35 (2008), offering a workaround to various compiler
- + \ No newline at end of file diff --git a/value_init_test.cpp b/value_init_test.cpp index 7191156..63f324d 100644 --- a/value_init_test.cpp +++ b/value_init_test.cpp @@ -9,6 +9,7 @@ // 21 Ago 2002 (Created) Fernando Cacciola // 15 Jan 2008 (Added tests regarding compiler issues) Fernando Cacciola, Niels Dekker // 23 May 2008 (Added tests regarding initialized_value) Niels Dekker +// 21 Ago 2008 (Added swap test) Niels Dekker #include // For memcmp. #include @@ -181,6 +182,35 @@ struct CopyFunctionCallTester }; +// +// A struct that allows testing whether its customized swap function is called. +// +struct SwapFunctionCallTester +{ + bool is_custom_swap_called; + int data; + + SwapFunctionCallTester() + : is_custom_swap_called(false), data(0) {} + + SwapFunctionCallTester(const SwapFunctionCallTester & arg) + : is_custom_swap_called(false), data(arg.data) {} + + void swap(SwapFunctionCallTester & arg) + { + std::swap(data, arg.data); + is_custom_swap_called = true; + arg.is_custom_swap_called = true; + } +}; + +void swap(SwapFunctionCallTester & lhs, SwapFunctionCallTester & rhs) +{ + lhs.swap(rhs); +} + + + template void check_initialized_value ( T const& y ) { @@ -196,7 +226,7 @@ void check_initialized_value( NonPOD const& ) // 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) @@ -323,9 +353,20 @@ int test_main(int, char **) BOOST_CHECK ( ! get(copyFunctionCallTester3).is_copy_constructed); BOOST_CHECK ( get(copyFunctionCallTester3).is_assignment_called); + boost::value_initialized swapFunctionCallTester1; + boost::value_initialized swapFunctionCallTester2; + get(swapFunctionCallTester1).data = 1; + get(swapFunctionCallTester2).data = 2; + boost::swap(swapFunctionCallTester1, swapFunctionCallTester2); + BOOST_CHECK( get(swapFunctionCallTester1).data == 2 ); + BOOST_CHECK( get(swapFunctionCallTester2).data == 1 ); + BOOST_CHECK( get(swapFunctionCallTester1).is_custom_swap_called ); + BOOST_CHECK( get(swapFunctionCallTester2).is_custom_swap_called ); + return 0; } unsigned int expected_failures = 0; +