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