summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/utility/test/value_init_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/utility/test/value_init_test.cpp')
-rw-r--r--src/boost/libs/utility/test/value_init_test.cpp371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/boost/libs/utility/test/value_init_test.cpp b/src/boost/libs/utility/test/value_init_test.cpp
new file mode 100644
index 00000000..ed7ec3d5
--- /dev/null
+++ b/src/boost/libs/utility/test/value_init_test.cpp
@@ -0,0 +1,371 @@
+// 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)
+//
+// Test program for "boost/utility/value_init.hpp"
+//
+// 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 <cstring> // For memcmp.
+#include <iostream>
+#include <string>
+
+#include "boost/utility/value_init.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include <boost/core/lightweight_test.hpp>
+
+//
+// Sample POD type
+//
+struct POD
+{
+ POD () : f(0), c(0), i(0){}
+
+ POD ( char c_, int i_, float f_ ) : f(f_), c(c_), i(i_) {}
+
+ friend std::ostream& operator << ( std::ostream& os, POD const& pod )
+ { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; }
+
+ friend bool operator == ( POD const& lhs, POD const& rhs )
+ { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
+
+ float f;
+ char c;
+ int i;
+} ;
+
+//
+// Sample non POD type
+//
+struct NonPODBase
+{
+ virtual ~NonPODBase() {}
+} ;
+struct NonPOD : NonPODBase
+{
+ NonPOD () : id() {}
+ explicit NonPOD ( std::string const& id_) : id(id_) {}
+
+ friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod )
+ { return os << '(' << npod.id << ')' ; }
+
+ friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs )
+ { return lhs.id == rhs.id ; }
+
+ std::string id ;
+} ;
+
+//
+// Sample aggregate POD struct type
+// Some compilers do not correctly value-initialize such a struct, for example:
+// Borland C++ Report #51854, "Value-initialization: POD struct should be zero-initialized "
+// http://qc.codegear.com/wc/qcmain.aspx?d=51854
+//
+struct AggregatePODStruct
+{
+ float f;
+ char c;
+ int i;
+};
+
+bool operator == ( AggregatePODStruct const& lhs, AggregatePODStruct const& rhs )
+{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
+
+//
+// An aggregate struct that contains an std::string and an int.
+// Pavel Kuznetsov (MetaCommunications Engineering) used a struct like
+// this to reproduce the Microsoft Visual C++ compiler bug, reported as
+// Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StringAndInt
+{
+ std::string s;
+ int i;
+};
+
+bool operator == ( StringAndInt const& lhs, StringAndInt const& rhs )
+{ return lhs.s == rhs.s && lhs.i == rhs.i ; }
+
+
+//
+// A struct that has an explicit (user defined) destructor.
+// Some compilers do not correctly value-initialize such a struct, for example:
+// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StructWithDestructor
+{
+ int i;
+ ~StructWithDestructor() {}
+};
+
+bool operator == ( StructWithDestructor const& lhs, StructWithDestructor const& rhs )
+{ return lhs.i == rhs.i ; }
+
+
+//
+// A struct that has a virtual function.
+// Some compilers do not correctly value-initialize such a struct either, for example:
+// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression"
+// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744
+//
+struct StructWithVirtualFunction
+{
+ int i;
+ virtual void VirtualFunction();
+};
+
+void StructWithVirtualFunction::VirtualFunction()
+{
+}
+
+bool operator == ( StructWithVirtualFunction const& lhs, StructWithVirtualFunction const& rhs )
+{ return lhs.i == rhs.i ; }
+
+
+//
+// A struct that is derived from an aggregate POD struct.
+// Some compilers do not correctly value-initialize such a struct, for example:
+// GCC Bugzilla Bug 30111, "Value-initialization of POD base class doesn't initialize members",
+// reported by Jonathan Wakely, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111
+//
+struct DerivedFromAggregatePODStruct : AggregatePODStruct
+{
+ DerivedFromAggregatePODStruct() : AggregatePODStruct() {}
+};
+
+//
+// A struct that wraps an aggregate POD struct as data member.
+//
+struct AggregatePODStructWrapper
+{
+ AggregatePODStructWrapper() : dataMember() {}
+ AggregatePODStruct dataMember;
+};
+
+bool operator == ( AggregatePODStructWrapper const& lhs, AggregatePODStructWrapper const& rhs )
+{ return lhs.dataMember == rhs.dataMember ; }
+
+typedef unsigned char ArrayOfBytes[256];
+
+
+//
+// A struct that allows testing whether the appropriate copy functions are called.
+//
+struct CopyFunctionCallTester
+{
+ bool is_copy_constructed;
+ bool is_assignment_called;
+
+ CopyFunctionCallTester()
+ : is_copy_constructed(false), is_assignment_called(false) {}
+
+ CopyFunctionCallTester(const CopyFunctionCallTester & )
+ : is_copy_constructed(true), is_assignment_called(false) {}
+
+ CopyFunctionCallTester & operator=(const CopyFunctionCallTester & )
+ {
+ is_assignment_called = true ;
+ return *this ;
+ }
+};
+
+
+//
+// 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<class T>
+void check_initialized_value ( T const& y )
+{
+ T initializedValue = boost::initialized_value ;
+ BOOST_TEST ( 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<T> for a specific type T.
+// The first argument (y) is assumed have the value of a value-initialized object.
+// Returns true on success.
+//
+template<class T>
+bool test ( T const& y, T const& z )
+{
+ const int errors_before_test = boost::detail::test_errors();
+
+ check_initialized_value(y);
+
+ boost::value_initialized<T> x ;
+ BOOST_TEST ( y == x ) ;
+ BOOST_TEST ( y == boost::get(x) ) ;
+
+ static_cast<T&>(x) = z ;
+ boost::get(x) = z ;
+ BOOST_TEST ( x == z ) ;
+
+ boost::value_initialized<T> const x_c ;
+ BOOST_TEST ( y == x_c ) ;
+ BOOST_TEST ( y == boost::get(x_c) ) ;
+ T& x_c_ref = const_cast<T&>( boost::get(x_c) ) ;
+ x_c_ref = z ;
+ BOOST_TEST ( x_c == z ) ;
+
+ boost::value_initialized<T> const copy1 = x;
+ BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ;
+
+ boost::value_initialized<T> copy2;
+ copy2 = x;
+ BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ;
+
+ {
+ boost::value_initialized<T> * ptr = new boost::value_initialized<T>;
+ BOOST_TEST ( y == *ptr ) ;
+ delete ptr;
+ }
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ boost::value_initialized<T const> cx ;
+ BOOST_TEST ( y == cx ) ;
+ BOOST_TEST ( y == boost::get(cx) ) ;
+
+ boost::value_initialized<T const> const cx_c ;
+ BOOST_TEST ( y == cx_c ) ;
+ BOOST_TEST ( y == boost::get(cx_c) ) ;
+#endif
+
+ return boost::detail::test_errors() == errors_before_test ;
+}
+
+int main()
+{
+ BOOST_TEST ( test( 0,1234 ) ) ;
+ BOOST_TEST ( test( 0.0,12.34 ) ) ;
+ BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ;
+ BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ;
+
+ NonPOD NonPOD_object( std::string("NonPOD_object") );
+ BOOST_TEST ( test<NonPOD *>( 0, &NonPOD_object ) ) ;
+
+ AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 };
+ AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 };
+ BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) );
+
+ StringAndInt stringAndInt0;
+ StringAndInt stringAndInt1;
+ stringAndInt0.i = 0;
+ stringAndInt1.i = 1;
+ stringAndInt1.s = std::string("1");
+ BOOST_TEST ( test(stringAndInt0, stringAndInt1) );
+
+ StructWithDestructor structWithDestructor0;
+ StructWithDestructor structWithDestructor1;
+ structWithDestructor0.i = 0;
+ structWithDestructor1.i = 1;
+ BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) );
+
+ StructWithVirtualFunction structWithVirtualFunction0;
+ StructWithVirtualFunction structWithVirtualFunction1;
+ structWithVirtualFunction0.i = 0;
+ structWithVirtualFunction1.i = 1;
+ BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) );
+
+ DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0;
+ DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1;
+ static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct;
+ static_cast<AggregatePODStruct &>(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct;
+ BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) );
+
+ AggregatePODStructWrapper aggregatePODStructWrapper0;
+ AggregatePODStructWrapper aggregatePODStructWrapper1;
+ aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct;
+ aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct;
+ BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) );
+
+ ArrayOfBytes zeroInitializedArrayOfBytes = { 0 };
+ boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes;
+ BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0);
+
+ boost::value_initialized<ArrayOfBytes> valueInitializedArrayOfBytes2;
+ valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes;
+ BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0);
+
+ boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester1;
+ BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed);
+ BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called);
+
+ boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester2 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
+ BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed);
+ BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called);
+
+ boost::value_initialized<CopyFunctionCallTester> copyFunctionCallTester3;
+ copyFunctionCallTester3 = boost::value_initialized<CopyFunctionCallTester>(copyFunctionCallTester1);
+ BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed);
+ BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called);
+
+ boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester1;
+ boost::value_initialized<SwapFunctionCallTester> swapFunctionCallTester2;
+ get(swapFunctionCallTester1).data = 1;
+ get(swapFunctionCallTester2).data = 2;
+ boost::swap(swapFunctionCallTester1, swapFunctionCallTester2);
+ BOOST_TEST( get(swapFunctionCallTester1).data == 2 );
+ BOOST_TEST( get(swapFunctionCallTester2).data == 1 );
+ BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called );
+ BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called );
+
+ return boost::report_errors();
+}
+
+