1 /*=========================================================================
4 Module: $RCSfile: bbtkAny.h,v $
6 Date: $Date: 2008/10/02 12:29:26 $
7 Version: $Revision: 1.4 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See doc/license.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
20 *\brief Defines the class any which can store any type of data (adapted from boost::any).
22 #ifndef __BBTKANY_H_INCLUDED__
23 #define __BBTKANY_H_INCLUDED__
38 #include "bbtkMessageManager.h"
39 #include "bbtkException.h"
41 #include <boost/type_traits/is_pointer.hpp>
50 //=========================================================
51 /// Abstract class used by the any class to store values
56 virtual ~anyplaceholder() {}
60 /// returns the type of the held value
61 virtual const std::type_info & type() const = 0;
62 /// returns the type of the pointed held value
63 virtual const std::type_info & pointed_type() const = 0;
65 /// returns true iff the stored value is a pointer
66 virtual bool is_pointer() const = 0;
68 /// If the held value is a pointer then
70 virtual void* get_pointer() const = 0;
73 virtual void* get_pointer_to( const std::type_info& ) const = 0;
75 virtual anyplaceholder * clone() const = 0;
78 //=========================================================
80 //=========================================================
81 /// Concrete template class used by the any class to store values
82 /// which stores a value of type ValueType
83 template<typename ValueType>
84 class anyholder : public anyplaceholder
88 anyholder(const ValueType & value)
94 virtual const std::type_info & type() const { return typeid(ValueType);}
95 virtual bool is_pointer() const { return false; }
96 virtual const std::type_info & pointed_type() const { return typeid(void); }
97 virtual void* get_pointer() const { return 0; }
98 virtual void* get_pointer_to( const std::type_info& ) const { return 0; }
99 virtual anyplaceholder * clone() const { return new anyholder(held); }
101 public: // representation
106 //=========================================================
108 //=========================================================
109 /// specialization of anyholder for pointer types
110 template<typename ValueType>
111 class anyholder<ValueType*> : public anyplaceholder
115 anyholder(ValueType* const & value)
121 virtual const std::type_info & type() const
123 return typeid(ValueType*);
126 virtual bool is_pointer() const { return true; }
127 virtual const std::type_info & pointed_type() const { return typeid(ValueType); }
128 virtual void* get_pointer() const {
131 virtual void* get_pointer_to( const std::type_info& t) const
133 return run_time_up_or_down_cast(t,typeid(ValueType),held);
136 virtual anyplaceholder * clone() const { return new anyholder(held); }
138 public: // representation
143 //=========================================================
146 /** A magic class which can store any type of data which
147 * is allowed by the template template parameter TypeTrait.
149 * The only requirement on TypeTrait<T> is to have the member :
150 * static const bool value;
151 * which is true iff the type T is an allowed type
153 * TypeTraits compliant objects are usually template structs
154 * for which the initialisation of value is set to false by default
155 * and set to true for the allowed types (template specialisation)
157 * template <typename T> struct mytypes { static const bool value; };
158 * template <typename T> const bool mytypes<T>::value = false;
159 * template <> const bool mytypes<int>::value = true;
160 * template <> const bool mytypes<float>::value = true;
162 * You can use any boost type_trait, like is_pointer, is_floating_point, etc.
164 * The class any is a generalisation of the boost::any class
165 * (see http://www.boost.org/doc/html/any.html).
166 * The boost::any class itself is reproduced by any<thing>,
167 * where thing is a TypeTrait whose value is true for all types.
169 template <template <class> class TypeTraits >
173 typedef any< TypeTraits > self;
176 /// Default constructor
182 /// Constructor with a value of template type
183 template<typename ValueType>
184 any(const ValueType & value)
187 bbtkDebugMessage("Data",1,
188 bbtk::HumanTypeName<self>()<<" construction with <"
189 <<bbtk::HumanTypeName<ValueType>()<<">"<<std::endl);
190 // ValueType v = value;
191 // int** i = (int**)(&v);
192 // std::cout << "v="<<*i<<std::endl;
194 if (accepts<ValueType>())
196 content = new anyholder<ValueType>(value);
200 bbtkError(bbtk::HumanTypeName<self>()
201 <<" constructor : data of type <"
202 <<bbtk::HumanTypeName<ValueType>()
203 <<"> are not accepted by traits <"
204 <<bbtk::HumanTypeName<TypeTraits<void> >()<<"> ");
209 any(const any & other)
210 : content(other.content ? other.content->clone() : 0)
212 bbtkDebugMessage("Data",1,
213 HumanTypeName<self>()
214 <<" copy construction with new content : "
215 <<HumanTypeName(type())
226 /// Swaps the content of this with another any
227 any & swap(any & rhs)
229 std::swap(content, rhs.content);
233 /// Affectation of a value of template type
234 template<typename ValueType>
235 any & operator=(const ValueType & rhs)
237 bbtkDebugMessage("Data",1,
238 HumanTypeName<self>()
239 <<" operator= with data of type <"
240 <<HumanTypeName<ValueType>()
242 if (accepts<ValueType>())
244 any(rhs).swap(*this);
249 bbtkError(HumanTypeName<self>()
250 <<" operator= : data of type <"
251 <<HumanTypeName<ValueType>()
252 <<"> are not accepted by traits <"
253 <<HumanTypeName<TypeTraits<void> >()<<"> ");
258 /// Affectation of another any
259 any & operator=(const any & rhs)
261 bbtkDebugMessage("Data",1,
262 HumanTypeName<self >()
263 <<" operator=(const any&) with content : "
264 <<HumanTypeName(rhs.type())<<std::endl);
266 any(rhs).swap(*this);
271 /// Is it empty (no value held) ?
277 /// Returns the type_info of the held value
278 const std::type_info & type() const
280 return content ? content->type() : typeid(void);
283 /// Returns the type_info of the pointed held value
284 const std::type_info & pointed_type() const
286 return content ? content->pointed_type() : typeid(void);
290 /// Returns true iff the contained type is Type
291 template<typename Type>
292 inline bool contains()
294 return ( type() == typeid(Type) );
297 /// Returns true iff the contained type is a pointer
298 inline bool contains_pointer()
300 return content->is_pointer() ;
303 /// Returns true iff the contained type is t
304 inline bool contains(TypeInfo t)
306 return ( (bool)(type() == t) );
309 /// Returns true iff any of type ValueType can be held
310 template<typename Type>
311 inline bool accepts()
313 return TypeTraits<Type>::value; //is_valid();
316 /// Returns a const reference on the held value iff its type matches
317 /// the template parameter
318 template<typename ValueType>
319 inline const ValueType& get() const
321 bbtkDebugMessage("Data",1,
322 HumanTypeName<self >()
323 <<" get<"<<HumanTypeName<ValueType>()
324 <<"> with content : "
325 <<HumanTypeName(type())<<std::endl);
327 if ( type() == typeid(ValueType) )
328 return static_cast< anyholder<ValueType> *>(content)->held;
330 bbtkError(HumanTypeName<self >()
332 <<bbtk::HumanTypeName<ValueType>()
333 <<"> does not match content type <"
334 <<bbtk::HumanTypeName<>(type())<<">");
337 template<typename ValueType>
338 inline const ValueType* getP() const
340 if ( type() == typeid(ValueType) )
341 return &static_cast< anyholder<ValueType> *>(content)->held;
343 bbtkError(HumanTypeName<self >()
344 <<" getP with type <"
345 <<bbtk::HumanTypeName<ValueType>()
346 <<"> does not match content type <"
347 <<bbtk::HumanTypeName<>(type())<<">");
350 /// Returns a const reference on the held value
351 /// ** EVEN IF ITS TYPE DOES NOT MATCH THE TEMPLATE PARAMETER **
352 /// Hence must be used when one knows that the type is good
353 /// Otherwise can lead to unpredictible results
354 template<typename ValueType>
355 inline const ValueType& unsafe_get() const
357 bbtkDebugMessage("Data",1,
358 HumanTypeName<self>()
360 <<HumanTypeName<ValueType>()<<"> with content : "
361 <<HumanTypeName(this->type())
364 // PrintValueIfIsPointer<ValueType>(static_cast< anyholder<ValueType> * >(content)->held);
365 // int** i = (int**)(&static_cast< anyholder<ValueType> * >(content)->held);
366 // std::cout << "v="<<*i<<std::endl;
369 return static_cast< anyholder<ValueType> * >(content)->held;
371 bbtkError(HumanTypeName<self >()
373 <<bbtk::HumanTypeName<ValueType>()
374 <<"> : void content");
378 inline void* get_pointer() const
380 void* p = content->get_pointer();
381 bbtkDebugMessage("Data",1,
382 HumanTypeName<self>()
383 <<"::get_pointer() with content <"
384 <<HumanTypeName(this->type())
391 inline void* get_pointer_to(const std::type_info& t) const
393 void* p = content->get_pointer_to(t);
394 bbtkDebugMessage("Data",1,
395 HumanTypeName<self>()
396 <<"::get_pointer_to("<<HumanTypeName(t)
398 <<HumanTypeName(this->type())
407 anyplaceholder * content;
413 /// The TypeTraits which validates any type
414 template <typename T> struct thing { static const bool value = true; };
416 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
419 /// The TypeTraits which validates all integer types
420 template <typename T> struct integer { static const bool value; };
421 template <class T> const bool integer<T>::value = false;
423 /// The TypeTraits which validates all floating point number types
424 template <typename T> struct floating_point { static const bool value; };
425 template <class T> const bool floating_point<T>::value = false;
428 /// The TypeTraits which validates all numerical types
429 template <typename T> struct number { static const bool value; };
430 template <class T> const bool number<T>::value =
431 integer<T>::value || floating_point<T>::value ;
434 /// Macro to begin the enumeration of types included into a
435 /// any_type_collection previously declared with
436 /// DECLARE_any_type_collection.
437 /// Must be placed in the implementation part of the code.
438 #define BBTK_DECLARE_TYPE_TRAITS(NAME) \
439 template <typename T> struct NAME { static const bool value; }; \
440 template <class T> const bool NAME<T>::value = false;
442 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
443 template <> bool NAME<TYPE>::value = true;