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