1 // file      : cutl/container/any.hxx
2 // copyright : Copyright (c) 2009-2017 Code Synthesis Tools CC
3 // license   : MIT; see accompanying LICENSE file
4 
5 #ifndef CUTL_CONTAINER_ANY_HXX
6 #define CUTL_CONTAINER_ANY_HXX
7 
8 #include <memory>   // std::unique_ptr/auto_ptr
9 #include <typeinfo> // std::type_info
10 
11 #include <cutl/exception.hxx>
12 
13 namespace cutl
14 {
15   namespace container
16   {
17     class any
18     {
19     public:
20       struct typing: exception {};
21 
22     public:
any()23       any ()
24       {
25       }
26 
27       template <typename X>
any(X const & x)28       any (X const& x)
29           : holder_ (new holder_impl<X> (x))
30       {
31       }
32 
any(any const & x)33       any (any const& x)
34           : holder_ (x.holder_->clone ())
35       {
36       }
37 
38       template <typename X>
39       any&
operator =(X const & x)40       operator= (X const& x)
41       {
42         holder_.reset (new holder_impl<X> (x));
43         return *this;
44       }
45 
46       any&
operator =(any const & x)47       operator= (any const& x)
48       {
49         holder_.reset (x.holder_->clone ());
50         return *this;
51       }
52 
53     public:
54       template <typename X>
55       X&
value()56       value ()
57       {
58         if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
59           return p->value ();
60         else
61           throw typing ();
62       }
63 
64       template <typename X>
65       X const&
value() const66       value () const
67       {
68         if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
69           return p->value ();
70         else
71           throw typing ();
72       }
73 
74       std::type_info const&
type_info() const75       type_info () const
76       {
77         return holder_->type_info ();
78       }
79 
80     public:
81       bool
empty() const82       empty () const
83       {
84         return holder_.get () == 0;
85       }
86 
87       void
reset()88       reset ()
89       {
90         return holder_.reset ();
91       }
92 
93     private:
94       class LIBCUTL_EXPORT holder
95       {
96       public:
97         virtual
~holder()98         ~holder () {}
99 
100         virtual holder*
101         clone () const = 0;
102 
103         virtual std::type_info const&
104         type_info () const = 0;
105       };
106 
107       template <typename X>
108       class holder_impl: public holder
109       {
110       public:
holder_impl(X const & x)111         holder_impl (X const& x)
112             : x_ (x)
113         {
114         }
115 
116         virtual holder_impl*
clone() const117         clone () const
118         {
119           return new holder_impl (x_);
120         }
121 
122         virtual std::type_info const&
type_info() const123         type_info () const
124         {
125           return typeid (x_);
126         }
127 
128         X const&
value() const129         value () const
130         {
131           return x_;
132         }
133 
134         X&
value()135         value ()
136         {
137           return x_;
138         }
139 
140       private:
141         X x_;
142       };
143 
144     private:
145 #ifdef LIBCUTL_CXX11
146       std::unique_ptr<holder> holder_;
147 #else
148       std::auto_ptr<holder> holder_;
149 #endif
150     };
151   }
152 }
153 
154 #endif // CUTL_CONTAINER_ANY_HXX
155