1 /*=========================================================================
3 Module: $RCSfile: bbtkAny.h,v $
5 Date: $Date: 2009/03/30 14:42:16 $
6 Version: $Revision: 1.7 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
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.
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
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 * ------------------------------------------------------------------------ */
32 /* ---------------------------------------------------------------------
34 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
35 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
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.
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
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 * ------------------------------------------------------------------------ */
56 *\brief Defines the class any which can store any type of data (adapted from boost::any).
58 #ifndef __BBTKANY_H_INCLUDED__
59 #define __BBTKANY_H_INCLUDED__
74 #include "bbtkMessageManager.h"
75 #include "bbtkException.h"
77 #include <boost/type_traits/is_pointer.hpp>
86 //=========================================================
87 /// Abstract class used by the any class to store values
92 virtual ~anyplaceholder() {}
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;
101 /// returns true iff the stored value is a pointer
102 virtual bool is_pointer() const = 0;
104 /// If the held value is a pointer then
105 /// returns its value
106 virtual void* get_pointer() const = 0;
109 virtual void* get_pointer_to( const std::type_info& ) const = 0;
111 virtual anyplaceholder * clone() const = 0;
114 //=========================================================
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
124 anyholder(const ValueType & value)
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); }
137 public: // representation
142 //=========================================================
144 //=========================================================
145 /// specialization of anyholder for pointer types
146 template<typename ValueType>
147 class anyholder<ValueType*> : public anyplaceholder
151 anyholder(ValueType* const & value)
157 virtual const std::type_info & type() const
159 return typeid(ValueType*);
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 {
167 virtual void* get_pointer_to( const std::type_info& t) const
169 return run_time_up_or_down_cast(t,typeid(ValueType),held);
172 virtual anyplaceholder * clone() const { return new anyholder(held); }
174 public: // representation
179 //=========================================================
182 /** A magic class which can store any type of data which
183 * is allowed by the template template parameter TypeTrait.
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
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)
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;
198 * You can use any boost type_trait, like is_pointer, is_floating_point, etc.
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.
205 template <template <class> class TypeTraits >
209 typedef any< TypeTraits > self;
212 /// Default constructor
218 /// Constructor with a value of template type
219 template<typename ValueType>
220 any(const ValueType & value)
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;
230 if (accepts<ValueType>())
232 content = new anyholder<ValueType>(value);
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> >()<<"> ");
245 any(const any & other)
246 : content(other.content ? other.content->clone() : 0)
248 bbtkDebugMessage("Data",1,
249 HumanTypeName<self>()
250 <<" copy construction with new content : "
251 <<HumanTypeName(type())
262 /// Swaps the content of this with another any
263 any & swap(any & rhs)
265 std::swap(content, rhs.content);
269 /// Affectation of a value of template type
270 template<typename ValueType>
271 any & operator=(const ValueType & rhs)
273 bbtkDebugMessage("Data",1,
274 HumanTypeName<self>()
275 <<" operator= with data of type <"
276 <<HumanTypeName<ValueType>()
278 if (accepts<ValueType>())
280 any(rhs).swap(*this);
285 bbtkError(HumanTypeName<self>()
286 <<" operator= : data of type <"
287 <<HumanTypeName<ValueType>()
288 <<"> are not accepted by traits <"
289 <<HumanTypeName<TypeTraits<void> >()<<"> ");
294 /// Affectation of another any
295 any & operator=(const any & rhs)
297 bbtkDebugMessage("Data",1,
298 HumanTypeName<self >()
299 <<" operator=(const any&) with content : "
300 <<HumanTypeName(rhs.type())<<std::endl);
302 any(rhs).swap(*this);
307 /// Is it empty (no value held) ?
313 /// Returns the type_info of the held value
314 const std::type_info & type() const
316 return content ? content->type() : typeid(void);
319 /// Returns the type_info of the pointed held value
320 const std::type_info & pointed_type() const
322 return content ? content->pointed_type() : typeid(void);
326 /// Returns true iff the contained type is Type
327 template<typename Type>
328 inline bool contains()
330 return ( type() == typeid(Type) );
333 /// Returns true iff the contained type is a pointer
334 inline bool contains_pointer()
336 return content ? content->is_pointer() : false;
339 /// Returns true iff the contained type is t
340 inline bool contains(TypeInfo t)
342 return ( (bool)((type() == t)!=0) );
345 /// Returns true iff any of type ValueType can be held
346 template<typename Type>
347 inline bool accepts()
349 return TypeTraits<Type>::value; //is_valid();
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
357 bbtkDebugMessage("Data",1,
358 HumanTypeName<self >()
359 <<" get<"<<HumanTypeName<ValueType>()
360 <<"> with content : "
361 <<HumanTypeName(type())<<std::endl);
363 if ( type() == typeid(ValueType) )
364 return static_cast< anyholder<ValueType> *>(content)->held;
366 bbtkError(HumanTypeName<self >()
368 <<bbtk::HumanTypeName<ValueType>()
369 <<"> does not match content type <"
370 <<bbtk::HumanTypeName<>(type())<<">");
373 template<typename ValueType>
374 inline const ValueType* getP() const
376 if ( type() == typeid(ValueType) )
377 return &static_cast< anyholder<ValueType> *>(content)->held;
379 bbtkError(HumanTypeName<self >()
380 <<" getP with type <"
381 <<bbtk::HumanTypeName<ValueType>()
382 <<"> does not match content type <"
383 <<bbtk::HumanTypeName<>(type())<<">");
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
393 bbtkDebugMessage("Data",1,
394 HumanTypeName<self>()
396 <<HumanTypeName<ValueType>()<<"> with content : "
397 <<HumanTypeName(this->type())
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;
405 return static_cast< anyholder<ValueType> * >(content)->held;
407 bbtkError(HumanTypeName<self >()
409 <<bbtk::HumanTypeName<ValueType>()
410 <<"> : void content");
414 inline void* get_pointer() const
416 void* p = content->get_pointer();
417 bbtkDebugMessage("Data",1,
418 HumanTypeName<self>()
419 <<"::get_pointer() with content <"
420 <<HumanTypeName(this->type())
427 inline void* get_pointer_to(const std::type_info& t) const
429 void* p = content->get_pointer_to(t);
430 bbtkDebugMessage("Data",1,
431 HumanTypeName<self>()
432 <<"::get_pointer_to("<<HumanTypeName(t)
434 <<HumanTypeName(this->type())
443 anyplaceholder * content;
449 /// The TypeTraits which validates any type
450 template <typename T> struct thing { static const bool value = true; };
452 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
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;
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;
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 ;
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;
478 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
479 template <> bool NAME<TYPE>::value = true;