]> Creatis software - bbtk.git/blob - kernel/src/bbtkAny.h
*** empty log message ***
[bbtk.git] / kernel / src / bbtkAny.h
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkAny.h,v $
5   Language:  C++
6   Date:      $Date: 2008/04/24 10:11:27 $
7   Version:   $Revision: 1.3 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See doc/license.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 /**
19  *\file
20  *\brief  Defines the class any which can store any type of data (adapted from boost::any).
21  */
22 #ifndef __BBTKANY_H_INCLUDED__
23 #define __BBTKANY_H_INCLUDED__
24
25 /*
26 #include <string>
27 #include <iostream>
28 #include <typeinfo>
29 #include <set>
30 #include <map>
31 #include <sstream>
32 #include <exception>
33
34 #include <cxxabi.h>
35 */
36 #include <sstream>
37 #include "bbtkRTTI.h"
38 #include "bbtkMessageManager.h"
39 #include "bbtkException.h"
40
41 #include <boost/type_traits/is_pointer.hpp>
42
43 namespace bbtk 
44 {
45
46
47
48
49
50   //=========================================================
51   /// Abstract class used by the any class to store values
52   class anyplaceholder
53   {
54   public: // structors
55     
56     virtual ~anyplaceholder() {}
57     
58   public: // queries
59     
60     /// returns the type of the held value
61     virtual const std::type_info & type() const = 0;
62     /// returns the type of the pointed held value
63     virtual const std::type_info & pointed_type() const = 0;
64     
65     /// returns true iff the stored value is a pointer
66     virtual bool is_pointer() const = 0;
67     
68     /// If the held value is a pointer then 
69     /// returns its value
70     virtual void* get_pointer() const = 0;
71  
72     /// 
73     virtual void* get_pointer_to( const std::type_info& ) const = 0;
74    
75     virtual anyplaceholder * clone() const = 0;
76     
77   };
78   //=========================================================
79   
80   //=========================================================
81   /// Concrete template class used by the any class to store values
82   /// which stores a value of type ValueType
83   template<typename ValueType>
84   class anyholder : public anyplaceholder
85   {
86   public: // structors
87     
88     anyholder(const ValueType & value)
89       : held(value)
90     {}
91     
92   public: // queries
93     
94     virtual const std::type_info & type() const { return typeid(ValueType);}
95     virtual bool is_pointer() const { return false; }
96     virtual const std::type_info & pointed_type() const { return typeid(void); }
97     virtual void* get_pointer() const { return 0; }
98     virtual void* get_pointer_to( const std::type_info& ) const { return 0; }
99     virtual anyplaceholder * clone() const { return new anyholder(held); }
100     
101     public: // representation
102     
103     ValueType held;
104     
105   };
106   //=========================================================
107   
108   //=========================================================
109   /// specialization of anyholder for pointer types
110   template<typename ValueType>
111   class anyholder<ValueType*> : public anyplaceholder
112   {
113   public: // structors
114
115     anyholder(ValueType* const & value)
116       : held(value)
117     { }
118
119   public: // queries
120
121     virtual const std::type_info & type() const
122     {
123       return typeid(ValueType*);
124     }
125
126     virtual bool is_pointer() const { return true; }
127     virtual const std::type_info & pointed_type() const { return typeid(ValueType); }
128     virtual void* get_pointer() const { 
129       return (void*)held; 
130     }
131     virtual void* get_pointer_to( const std::type_info& t) const 
132     { 
133       return run_time_up_or_down_cast(t,typeid(ValueType),held);
134     }
135
136     virtual anyplaceholder * clone() const { return new anyholder(held); }
137
138   public: // representation
139
140     ValueType* held;
141
142   };
143   //=========================================================
144
145
146   /** A magic class which can store any type of data which 
147    * is allowed by the template template parameter TypeTrait.
148    *
149    * The only requirement on TypeTrait<T> is to have the member :
150    *    static const bool value;
151    * which is true iff the type T is an allowed type 
152    * 
153    * TypeTraits compliant objects are usually template structs 
154    * for which the initialisation of value is set to false by default 
155    * and set to true for the allowed types (template specialisation)
156    * Example :
157    *   template <typename T> struct mytypes { static const bool value; };
158    *   template <typename T> const bool mytypes<T>::value = false;
159    *   template <> const bool mytypes<int>::value = true;
160    *   template <> const bool mytypes<float>::value = true; 
161    * etc.
162    * You can use any boost type_trait, like is_pointer, is_floating_point, etc.
163    *
164    * The class any is a generalisation of the boost::any class 
165    * (see http://www.boost.org/doc/html/any.html).
166    * The boost::any class itself is reproduced by any<thing>,
167    * where thing is a TypeTrait whose value is true for all types.
168    **/
169   template <template <class> class TypeTraits >
170   class any
171   {
172   public:
173     typedef any< TypeTraits > self;
174     // structors
175
176     /// Default constructor
177     any()
178       : content(0)
179     {
180     }
181
182     /// Constructor with a value of template type
183     template<typename ValueType>
184     any(const ValueType & value)
185       : content(0)
186     {
187       bbtkDebugMessage("Data",1,
188                        bbtk::HumanTypeName<self>()<<" construction with <"
189                        <<bbtk::HumanTypeName<ValueType>()<<">"<<std::endl);
190       //      ValueType v = value;
191       //      int** i = (int**)(&v);
192       //      std::cout << "v="<<*i<<std::endl;
193       
194       if (accepts<ValueType>()) 
195         { 
196           content = new anyholder<ValueType>(value);
197         }
198       else 
199         {
200           bbtkError(bbtk::HumanTypeName<self>()
201                     <<" constructor : data of type <"
202                     <<bbtk::HumanTypeName<ValueType>()
203                     <<"> are not accepted by traits <"
204                     <<bbtk::HumanTypeName<TypeTraits<void> >()<<"> ");
205         }
206     }
207   
208     /// Copy constructor
209     any(const any & other)
210       : content(other.content ? other.content->clone() : 0)
211     {
212       bbtkDebugMessage("Data",1,
213                        HumanTypeName<self>()
214                        <<" copy construction with new content : "
215                        <<HumanTypeName(type())
216                        <<std::endl);
217     }
218   
219     /// Destructor
220     ~any()
221     {
222       delete content;
223     }
224
225
226     /// Swaps the content of this with another any
227     any & swap(any & rhs)
228     {
229       std::swap(content, rhs.content);
230       return *this;
231     }
232
233     /// Affectation of a value of template type
234     template<typename ValueType>
235     any & operator=(const ValueType & rhs)
236     {
237       bbtkDebugMessage("Data",1,
238                        HumanTypeName<self>()
239                        <<" operator= with data of type <"
240                        <<HumanTypeName<ValueType>()
241                        <<">"<<std::endl);
242       if (accepts<ValueType>()) 
243         {
244           any(rhs).swap(*this);
245           return *this;
246         }
247       else 
248         {
249           bbtkError(HumanTypeName<self>()
250                     <<" operator= : data of type <"
251                     <<HumanTypeName<ValueType>()
252                     <<"> are not accepted by traits <"
253                     <<HumanTypeName<TypeTraits<void> >()<<"> ");
254         }
255     
256     }
257   
258     /// Affectation of another any
259     any & operator=(const any & rhs)
260     {
261         bbtkDebugMessage("Data",1,
262                          HumanTypeName<self >()
263                          <<" operator=(const any&) with content : "
264                          <<HumanTypeName(rhs.type())<<std::endl);
265
266       any(rhs).swap(*this);
267       return *this;
268     }
269   
270
271     /// Is it empty (no value held) ?
272     bool empty() const
273     {
274       return !content;
275     }
276   
277     /// Returns the type_info of the held value
278     const std::type_info & type() const
279     {
280       return content ? content->type() : typeid(void);
281     }
282
283     /// Returns the type_info of the pointed held value
284     const std::type_info & pointed_type() const
285     {
286       return content ? content->pointed_type() : typeid(void);
287     }
288
289
290     /// Returns true iff the contained type is Type
291     template<typename Type>
292     inline bool contains()
293     {
294       return ( type() == typeid(Type) );
295     }
296
297     /// Returns true iff the contained type is a pointer
298     inline bool contains_pointer()
299     {
300       return content->is_pointer() ;
301     }
302
303     /// Returns true iff the contained type is t
304     inline bool contains(TypeInfo t)
305     {
306       return ( type() == t );
307      }
308
309     /// Returns true iff any of type ValueType can be held 
310     template<typename Type>
311     inline bool accepts()
312     {
313       return TypeTraits<Type>::value; //is_valid();
314     }
315
316     /// Returns a const reference on the held value iff its type matches 
317     /// the template parameter  
318     template<typename ValueType>
319     inline const ValueType& get() const
320     {
321         bbtkDebugMessage("Data",1,
322                          HumanTypeName<self >()
323                          <<" get<"<<HumanTypeName<ValueType>()
324                          <<"> with content : "
325                          <<HumanTypeName(type())<<std::endl);
326
327       if ( type() == typeid(ValueType) )
328         return static_cast< anyholder<ValueType> *>(content)->held;
329
330       bbtkError(HumanTypeName<self >()
331                 <<" get with type <"
332                 <<bbtk::HumanTypeName<ValueType>()
333                 <<"> does not match content type <"
334                 <<bbtk::HumanTypeName<>(type())<<">");
335     }
336
337     template<typename ValueType>
338     inline const ValueType* getP() const
339     {
340       if ( type() == typeid(ValueType) )
341         return &static_cast< anyholder<ValueType> *>(content)->held;
342  
343       bbtkError(HumanTypeName<self >()
344                 <<" getP with type <"
345                 <<bbtk::HumanTypeName<ValueType>()
346                 <<"> does not match content type <"
347                 <<bbtk::HumanTypeName<>(type())<<">");
348     }
349
350     /// Returns a const reference on the held value 
351     /// ** EVEN IF ITS TYPE DOES NOT MATCH THE TEMPLATE PARAMETER **
352     /// Hence must be used when one knows that the type is good
353     /// Otherwise can lead to unpredictible results 
354     template<typename ValueType>
355     inline const ValueType& unsafe_get() const
356     {
357         bbtkDebugMessage("Data",1,
358                          HumanTypeName<self>()
359                          <<"::unsafe_get<"
360                          <<HumanTypeName<ValueType>()<<"> with content : "
361                          <<HumanTypeName(this->type())
362                          <<std::endl);
363
364         //      PrintValueIfIsPointer<ValueType>(static_cast< anyholder<ValueType> * >(content)->held);
365         //      int** i = (int**)(&static_cast< anyholder<ValueType> * >(content)->held);
366         //      std::cout << "v="<<*i<<std::endl;
367
368         if (content) 
369           return static_cast< anyholder<ValueType> * >(content)->held;
370         
371         bbtkError(HumanTypeName<self >()
372                   <<"::usafe_get<"
373                   <<bbtk::HumanTypeName<ValueType>()
374                   <<"> : void content");
375     }
376
377
378     inline void* get_pointer() const 
379     {
380       void* p = content->get_pointer();
381       bbtkDebugMessage("Data",1,
382                        HumanTypeName<self>()
383                        <<"::get_pointer() with content <"
384                        <<HumanTypeName(this->type())
385                        <<"> : result = "
386                        << p
387                        <<std::endl);
388       return p;
389     }
390     
391     inline void* get_pointer_to(const std::type_info& t) const 
392     {
393       void* p = content->get_pointer_to(t);
394       bbtkDebugMessage("Data",1,
395                        HumanTypeName<self>()
396                        <<"::get_pointer_to("<<HumanTypeName(t)
397                        <<") with content <"
398                        <<HumanTypeName(this->type())
399                        <<"> : result = "
400                        << p
401                        <<std::endl);
402       return p;
403     }
404     
405   private: 
406     /// content
407     anyplaceholder * content;
408     
409   };
410
411   
412
413   /// The TypeTraits which validates any type 
414   template <typename T> struct thing { static const bool value = true; };
415
416   BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
417
418
419   /// The TypeTraits which validates all integer types
420   template <typename T> struct integer { static const bool value; };
421   template <class T> const bool integer<T>::value = false;
422
423   /// The TypeTraits which validates all floating point number types
424   template <typename T> struct floating_point { static const bool value; };
425   template <class T> const bool floating_point<T>::value = false;
426
427
428   /// The TypeTraits which validates all numerical types
429   template <typename T> struct number { static const bool value; };
430   template <class T> const bool number<T>::value = 
431              integer<T>::value || floating_point<T>::value ;
432   
433   
434   /// Macro to begin the enumeration of types included into a 
435   /// any_type_collection previously declared with 
436   /// DECLARE_any_type_collection. 
437   /// Must be placed in the implementation part of the code.
438 #define BBTK_DECLARE_TYPE_TRAITS(NAME)                                  \
439   template <typename T> struct NAME { static const bool value; };       \
440     template <class T> const bool NAME<T>::value = false;
441   
442 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE)      \
443   template <> bool NAME<TYPE>::value = true;
444
445
446 }
447
448
449
450
451
452 #endif
453