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