1 /*=========================================================================
3 Module: $RCSfile: bbtkAny.h,v $
5 Date: $Date: 2010/01/14 13:17:27 $
6 Version: $Revision: 1.8 $
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 * ------------------------------------------------------------------------ */
34 *\brief Defines the class any which can store any type of data (adapted from boost::any).
36 #ifndef __BBTKANY_H_INCLUDED__
37 #define __BBTKANY_H_INCLUDED__
52 #include "bbtkMessageManager.h"
53 #include "bbtkException.h"
55 #include <boost/type_traits/is_pointer.hpp>
64 //=========================================================
65 /// Abstract class used by the any class to store values
70 virtual ~anyplaceholder() {}
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;
79 /// returns true iff the stored value is a pointer
80 virtual bool is_pointer() const = 0;
82 /// If the held value is a pointer then
84 virtual void* get_pointer() const = 0;
87 virtual void* get_pointer_to( const std::type_info& ) const = 0;
89 virtual anyplaceholder * clone() const = 0;
92 //=========================================================
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
102 anyholder(const ValueType & value)
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); }
115 public: // representation
120 //=========================================================
122 //=========================================================
123 /// specialization of anyholder for pointer types
124 template<typename ValueType>
125 class anyholder<ValueType*> : public anyplaceholder
129 anyholder(ValueType* const & value)
135 virtual const std::type_info & type() const
137 return typeid(ValueType*);
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 {
145 virtual void* get_pointer_to( const std::type_info& t) const
147 return run_time_up_or_down_cast(t,typeid(ValueType),held);
150 virtual anyplaceholder * clone() const { return new anyholder(held); }
152 public: // representation
157 //=========================================================
160 /** A magic class which can store any type of data which
161 * is allowed by the template template parameter TypeTrait.
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
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)
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;
176 * You can use any boost type_trait, like is_pointer, is_floating_point, etc.
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.
183 template <template <class> class TypeTraits >
187 typedef any< TypeTraits > self;
190 /// Default constructor
196 /// Constructor with a value of template type
197 template<typename ValueType>
198 any(const ValueType & value)
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;
208 if (accepts<ValueType>())
210 content = new anyholder<ValueType>(value);
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> >()<<"> ");
223 any(const any & other)
224 : content(other.content ? other.content->clone() : 0)
226 bbtkDebugMessage("Data",1,
227 HumanTypeName<self>()
228 <<" copy construction with new content : "
229 <<HumanTypeName(type())
240 /// Swaps the content of this with another any
241 any & swap(any & rhs)
243 std::swap(content, rhs.content);
247 /// Affectation of a value of template type
248 template<typename ValueType>
249 any & operator=(const ValueType & rhs)
251 bbtkDebugMessage("Data",1,
252 HumanTypeName<self>()
253 <<" operator= with data of type <"
254 <<HumanTypeName<ValueType>()
256 if (accepts<ValueType>())
258 any(rhs).swap(*this);
263 bbtkError(HumanTypeName<self>()
264 <<" operator= : data of type <"
265 <<HumanTypeName<ValueType>()
266 <<"> are not accepted by traits <"
267 <<HumanTypeName<TypeTraits<void> >()<<"> ");
272 /// Affectation of another any
273 any & operator=(const any & rhs)
275 bbtkDebugMessage("Data",1,
276 HumanTypeName<self >()
277 <<" operator=(const any&) with content : "
278 <<HumanTypeName(rhs.type())<<std::endl);
280 any(rhs).swap(*this);
285 /// Is it empty (no value held) ?
291 /// Returns the type_info of the held value
292 const std::type_info & type() const
294 return content ? content->type() : typeid(void);
297 /// Returns the type_info of the pointed held value
298 const std::type_info & pointed_type() const
300 return content ? content->pointed_type() : typeid(void);
304 /// Returns true iff the contained type is Type
305 template<typename Type>
306 inline bool contains()
308 return ( type() == typeid(Type) );
311 /// Returns true iff the contained type is a pointer
312 inline bool contains_pointer()
314 return content ? content->is_pointer() : false;
317 /// Returns true iff the contained type is t
318 inline bool contains(TypeInfo t)
320 return ( (bool)((type() == t)!=0) );
323 /// Returns true iff any of type ValueType can be held
324 template<typename Type>
325 inline bool accepts()
327 return TypeTraits<Type>::value; //is_valid();
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
335 bbtkDebugMessage("Data",1,
336 HumanTypeName<self >()
337 <<" get<"<<HumanTypeName<ValueType>()
338 <<"> with content : "
339 <<HumanTypeName(type())<<std::endl);
341 if ( type() == typeid(ValueType) )
342 return static_cast< anyholder<ValueType> *>(content)->held;
344 bbtkError(HumanTypeName<self >()
346 <<bbtk::HumanTypeName<ValueType>()
347 <<"> does not match content type <"
348 <<bbtk::HumanTypeName<>(type())<<">");
351 template<typename ValueType>
352 inline const ValueType* getP() const
354 if ( type() == typeid(ValueType) )
355 return &static_cast< anyholder<ValueType> *>(content)->held;
357 bbtkError(HumanTypeName<self >()
358 <<" getP with type <"
359 <<bbtk::HumanTypeName<ValueType>()
360 <<"> does not match content type <"
361 <<bbtk::HumanTypeName<>(type())<<">");
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
371 bbtkDebugMessage("Data",1,
372 HumanTypeName<self>()
374 <<HumanTypeName<ValueType>()<<"> with content : "
375 <<HumanTypeName(this->type())
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;
383 return static_cast< anyholder<ValueType> * >(content)->held;
385 bbtkError(HumanTypeName<self >()
387 <<bbtk::HumanTypeName<ValueType>()
388 <<"> : void content");
392 inline void* get_pointer() const
394 void* p = content->get_pointer();
395 bbtkDebugMessage("Data",1,
396 HumanTypeName<self>()
397 <<"::get_pointer() with content <"
398 <<HumanTypeName(this->type())
405 inline void* get_pointer_to(const std::type_info& t) const
407 void* p = content->get_pointer_to(t);
408 bbtkDebugMessage("Data",1,
409 HumanTypeName<self>()
410 <<"::get_pointer_to("<<HumanTypeName(t)
412 <<HumanTypeName(this->type())
421 anyplaceholder * content;
427 /// The TypeTraits which validates any type
428 template <typename T> struct thing { static const bool value = true; };
430 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
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;
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;
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 ;
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;
456 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
457 template <> bool NAME<TYPE>::value = true;