1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) 2 // (C) Copyright 2005-2007 Jonathan Turkanis 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 5 6 // See http://www.boost.org/libs/iostreams for documentation. 7 8 // Recent changes to Boost.Optional involving assigment broke Boost.Iostreams, 9 // in a way which could be remedied only by relying on the deprecated reset 10 // functions; with VC6, even reset didn't work. Until this problem is 11 // understood, Iostreams will use a private version of optional with a smart 12 // pointer interface. 13 14 #ifndef BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED 15 #define BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED 16 17 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 18 # pragma once 19 #endif 20 21 #include <boost/assert.hpp> 22 #include <boost/mpl/int.hpp> 23 #include <boost/type_traits/aligned_storage.hpp> 24 #include <boost/type_traits/alignment_of.hpp> 25 26 namespace boost { namespace iostreams { namespace detail { 27 28 // Taken from <boost/optional.hpp>. 29 template<class T> 30 class aligned_storage 31 { 32 // Borland ICEs if unnamed unions are used for this! 33 union dummy_u 34 { 35 char data[ sizeof(T) ]; 36 BOOST_DEDUCED_TYPENAME type_with_alignment< 37 ::boost::alignment_of<T>::value >::type aligner_; 38 } dummy_ ; 39 40 public: 41 address() const42 void const* address() const { return &dummy_.data[0]; } address()43 void * address() { return &dummy_.data[0]; } 44 }; 45 46 template<typename T> 47 class optional { 48 public: 49 typedef T element_type; optional()50 optional() : initialized_(false) { } optional(const T & t)51 optional(const T& t) : initialized_(false) { reset(t); } ~optional()52 ~optional() { reset(); } operator *()53 T& operator*() 54 { 55 BOOST_ASSERT(initialized_); 56 return *static_cast<T*>(address()); 57 } operator *() const58 const T& operator*() const 59 { 60 BOOST_ASSERT(initialized_); 61 return *static_cast<const T*>(address()); 62 } operator ->()63 T* operator->() 64 { 65 BOOST_ASSERT(initialized_); 66 return static_cast<T*>(address()); 67 } operator ->() const68 const T* operator->() const 69 { 70 BOOST_ASSERT(initialized_); 71 return static_cast<const T*>(address()); 72 } get()73 T* get() 74 { 75 BOOST_ASSERT(initialized_); 76 return static_cast<T*>(address()); 77 } get() const78 const T* get() const 79 { 80 BOOST_ASSERT(initialized_); 81 return static_cast<const T*>(address()); 82 } reset()83 void reset() 84 { 85 if (initialized_) { 86 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ 87 BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ 88 /**/ 89 T* t = static_cast<T*>(address()); 90 t->~T(); 91 #else 92 static_cast<T*>(address())->T::~T(); 93 #endif 94 initialized_ = false; 95 } 96 } reset(const T & t)97 void reset(const T& t) 98 { 99 reset(); 100 new (address()) T(t); 101 initialized_ = true; 102 } 103 private: 104 optional(const optional&); 105 optional& operator=(const optional&); address()106 void* address() { return &storage_; } address() const107 const void* address() const { return &storage_; } 108 aligned_storage<T> storage_; 109 bool initialized_; 110 }; 111 112 } } } // End namespaces detail, iostreams, boost. 113 114 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED 115