2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
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
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.
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
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 # ------------------------------------------------------------------------ */
28 /*=========================================================================
30 Module: $RCSfile: bbtkAny.h,v $
32 Date: $Date: 2012/11/16 08:49:01 $
33 Version: $Revision: 1.9 $
34 =========================================================================*/
40 *\brief Defines the class any which can store any type of data (adapted from boost::any).
42 #ifndef __BBTKANY_H_INCLUDED__
43 #define __BBTKANY_H_INCLUDED__
58 #include "bbtkMessageManager.h"
59 #include "bbtkException.h"
61 #include <boost/type_traits/is_pointer.hpp>
70 //=========================================================
71 /// Abstract class used by the any class to store values
76 virtual ~anyplaceholder() {}
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;
85 /// returns true iff the stored value is a pointer
86 virtual bool is_pointer() const = 0;
88 /// If the held value is a pointer then
90 virtual void* get_pointer() const = 0;
93 virtual void* get_pointer_to( const std::type_info& ) const = 0;
95 virtual anyplaceholder * clone() const = 0;
98 //=========================================================
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
108 anyholder(const ValueType & value)
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); }
121 public: // representation
126 //=========================================================
128 //=========================================================
129 /// specialization of anyholder for pointer types
130 template<typename ValueType>
131 class anyholder<ValueType*> : public anyplaceholder
135 anyholder(ValueType* const & value)
141 virtual const std::type_info & type() const
143 return typeid(ValueType*);
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 {
151 virtual void* get_pointer_to( const std::type_info& t) const
153 return run_time_up_or_down_cast(t,typeid(ValueType),held);
156 virtual anyplaceholder * clone() const { return new anyholder(held); }
158 public: // representation
163 //=========================================================
166 /** A magic class which can store any type of data which
167 * is allowed by the template template parameter TypeTrait.
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
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)
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;
182 * You can use any boost type_trait, like is_pointer, is_floating_point, etc.
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.
189 template <template <class> class TypeTraits >
193 typedef any< TypeTraits > self;
196 /// Default constructor
202 /// Constructor with a value of template type
203 template<typename ValueType>
204 any(const ValueType & value)
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;
214 if (accepts<ValueType>())
216 content = new anyholder<ValueType>(value);
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> >()<<"> ");
229 any(const any & other)
230 : content(other.content ? other.content->clone() : 0)
232 bbtkDebugMessage("Data",1,
233 HumanTypeName<self>()
234 <<" copy construction with new content : "
235 <<HumanTypeName(type())
246 /// Swaps the content of this with another any
247 any & swap(any & rhs)
249 std::swap(content, rhs.content);
253 /// Affectation of a value of template type
254 template<typename ValueType>
255 any & operator=(const ValueType & rhs)
257 bbtkDebugMessage("Data",1,
258 HumanTypeName<self>()
259 <<" operator= with data of type <"
260 <<HumanTypeName<ValueType>()
262 if (accepts<ValueType>())
264 any(rhs).swap(*this);
269 bbtkError(HumanTypeName<self>()
270 <<" operator= : data of type <"
271 <<HumanTypeName<ValueType>()
272 <<"> are not accepted by traits <"
273 <<HumanTypeName<TypeTraits<void> >()<<"> ");
278 /// Affectation of another any
279 any & operator=(const any & rhs)
281 bbtkDebugMessage("Data",1,
282 HumanTypeName<self >()
283 <<" operator=(const any&) with content : "
284 <<HumanTypeName(rhs.type())<<std::endl);
286 any(rhs).swap(*this);
291 /// Is it empty (no value held) ?
297 /// Returns the type_info of the held value
298 const std::type_info & type() const
300 return content ? content->type() : typeid(void);
303 /// Returns the type_info of the pointed held value
304 const std::type_info & pointed_type() const
306 return content ? content->pointed_type() : typeid(void);
310 /// Returns true iff the contained type is Type
311 template<typename Type>
312 inline bool contains()
314 //EED 2021-12-15 typeid comparation is not working in MacOs for objects declared in different libraries
315 // ex: itk <-> vtk templates convertion
317 if ( strcmp( type().name() , typeid(Type).name() ) ==0 ) return true; else return false;
319 return ( type() == typeid(Type) );
323 /// Returns true iff the contained type is a pointer
324 inline bool contains_pointer()
326 return content ? content->is_pointer() : false;
329 /// Returns true iff the contained type is t
330 inline bool contains(TypeInfo t)
332 //EED 2021-12-15 typeid comparation is not working in MacOs for objects declared in different libraries
333 // ex: itk <-> vtk templates convertion
335 bool compTmp = (strcmp( type().name() , t.name() ) == 0);
336 return ( compTmp!=0 );
338 return ( (bool)((type() == t)!=0) );
342 /// Returns true iff any of type ValueType can be held
343 template<typename Type>
344 inline bool accepts()
346 return TypeTraits<Type>::value; //is_valid();
349 /// Returns a const reference on the held value iff its type matches
350 /// the template parameter
351 template<typename ValueType>
352 inline const ValueType& get() const
354 bbtkDebugMessage("Data",1,
355 HumanTypeName<self >()
356 <<" get<"<<HumanTypeName<ValueType>()
357 <<"> with content : "
358 <<HumanTypeName(type())<<std::endl);
360 //EED 2021-12-15 typeid comparation is not working in MacOs for objects declared in different libraries
361 // ex: itk <-> vtk templates convertion
363 if ( strcmp( type().name() , typeid(ValueType).name() ) ==0 )
365 if ( type() == typeid(ValueType) )
368 return static_cast< anyholder<ValueType> *>(content)->held;
371 bbtkError(HumanTypeName<self >()
373 <<bbtk::HumanTypeName<ValueType>()
374 <<"> does not match content type <"
375 <<bbtk::HumanTypeName<>(type())<<">");
378 template<typename ValueType>
379 inline const ValueType* getP() const
381 //EED 2021-12-15 typeid comparation is not working in MacOs for objects declared in different libraries
382 // ex: itk <-> vtk templates convertion
384 if ( strcmp( type().name() , typeid(ValueType).name() ) ==0 )
386 if ( type() == typeid(ValueType) )
388 return &static_cast< anyholder<ValueType> *>(content)->held;
390 bbtkError(HumanTypeName<self >()
391 <<" getP with type <"
392 <<bbtk::HumanTypeName<ValueType>()
393 <<"> does not match content type <"
394 <<bbtk::HumanTypeName<>(type())<<">");
397 /// Returns a const reference on the held value
398 /// ** EVEN IF ITS TYPE DOES NOT MATCH THE TEMPLATE PARAMETER **
399 /// Hence must be used when one knows that the type is good
400 /// Otherwise can lead to unpredictible results
401 template<typename ValueType>
402 inline const ValueType& unsafe_get() const
404 bbtkDebugMessage("Data",1,
405 HumanTypeName<self>()
407 <<HumanTypeName<ValueType>()<<"> with content : "
408 <<HumanTypeName(this->type())
411 // PrintValueIfIsPointer<ValueType>(static_cast< anyholder<ValueType> * >(content)->held);
412 // int** i = (int**)(&static_cast< anyholder<ValueType> * >(content)->held);
413 // std::cout << "v="<<*i<<std::endl;
416 return static_cast< anyholder<ValueType> * >(content)->held;
418 bbtkError(HumanTypeName<self >()
420 <<bbtk::HumanTypeName<ValueType>()
421 <<"> : void content");
425 inline void* get_pointer() const
427 void* p = content->get_pointer();
428 bbtkDebugMessage("Data",1,
429 HumanTypeName<self>()
430 <<"::get_pointer() with content <"
431 <<HumanTypeName(this->type())
438 inline void* get_pointer_to(const std::type_info& t) const
440 void* p = content->get_pointer_to(t);
441 bbtkDebugMessage("Data",1,
442 HumanTypeName<self>()
443 <<"::get_pointer_to("<<HumanTypeName(t)
445 <<HumanTypeName(this->type())
454 anyplaceholder * content;
460 /// The TypeTraits which validates any type
461 template <typename T> struct thing { static const bool value = true; };
463 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
466 /// The TypeTraits which validates all integer types
467 template <typename T> struct integer { static const bool value; };
468 template <class T> const bool integer<T>::value = false;
470 /// The TypeTraits which validates all floating point number types
471 template <typename T> struct floating_point { static const bool value; };
472 template <class T> const bool floating_point<T>::value = false;
475 /// The TypeTraits which validates all numerical types
476 template <typename T> struct number { static const bool value; };
477 template <class T> const bool number<T>::value =
478 integer<T>::value || floating_point<T>::value ;
481 /// Macro to begin the enumeration of types included into a
482 /// any_type_collection previously declared with
483 /// DECLARE_any_type_collection.
484 /// Must be placed in the implementation part of the code.
485 #define BBTK_DECLARE_TYPE_TRAITS(NAME) \
486 template <typename T> struct NAME { static const bool value; }; \
487 template <class T> const bool NAME<T>::value = false;
489 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
490 template <> bool NAME<TYPE>::value = true;