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