1 // file      : cutl/container/any.hxx
2 // copyright : Copyright (c) 2009-2013 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::auto_ptr
9 #include <typeinfo> // std::type_info
10 
11 #include <cutl/exception.hxx>
12 
13 #include <cutl/details/export.hxx>
14 
15 namespace cutl
16 {
17   namespace container
18   {
19     class LIBCUTL_EXPORT any
20     {
21     public:
22       struct LIBCUTL_EXPORT typing: exception {};
23 
24     public:
any()25       any ()
26       {
27       }
28 
29       template <typename X>
any(X const & x)30       any (X const& x)
31           : holder_ (new holder_impl<X> (x))
32       {
33       }
34 
any(any const & x)35       any (any const& x)
36           : holder_ (x.holder_->clone ())
37       {
38       }
39 
40       template <typename X>
41       any&
operator =(X const & x)42       operator= (X const& x)
43       {
44         holder_.reset (new holder_impl<X> (x));
45         return *this;
46       }
47 
48       any&
operator =(any const & x)49       operator= (any const& x)
50       {
51         holder_.reset (x.holder_->clone ());
52         return *this;
53       }
54 
55     public:
56       template <typename X>
57       X&
value()58       value ()
59       {
60         if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
61           return p->value ();
62         else
63           throw typing ();
64       }
65 
66       template <typename X>
67       X const&
value() const68       value () const
69       {
70         if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
71           return p->value ();
72         else
73           throw typing ();
74       }
75 
76       std::type_info const&
type_info() const77       type_info () const
78       {
79         return holder_->type_info ();
80       }
81 
82     public:
83       bool
empty() const84       empty () const
85       {
86         return holder_.get () == 0;
87       }
88 
89       void
reset()90       reset ()
91       {
92         return holder_.reset ();
93       }
94 
95     private:
96       class LIBCUTL_EXPORT holder
97       {
98       public:
99         virtual
~holder()100         ~holder () {}
101 
102         virtual holder*
103         clone () const = 0;
104 
105         virtual std::type_info const&
106         type_info () const = 0;
107       };
108 
109       template <typename X>
110       class holder_impl: public holder
111       {
112       public:
holder_impl(X const & x)113         holder_impl (X const& x)
114             : x_ (x)
115         {
116         }
117 
118         virtual holder_impl*
clone() const119         clone () const
120         {
121           return new holder_impl (x_);
122         }
123 
124         virtual std::type_info const&
type_info() const125         type_info () const
126         {
127           return typeid (x_);
128         }
129 
130         X const&
value() const131         value () const
132         {
133           return x_;
134         }
135 
136         X&
value()137         value ()
138         {
139           return x_;
140         }
141 
142       private:
143         X x_;
144       };
145 
146     private:
147       std::auto_ptr<holder> holder_;
148     };
149   }
150 }
151 
152 #endif // CUTL_CONTAINER_ANY_HXX
153