1 /*=========================================================================
4 Module: $RCSfile: bbtkData.h,v $
6 Date: $Date: 2008/01/22 15:02:00 $
7 Version: $Revision: 1.1 $
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 Data and TypeInfo
22 * Data is bbtk general type exchanged between black boxes (adapted from boost::any).
23 * TypeInfo is the bbtk type of object storing informations on a data type (typedef on std::type_info).
26 #ifndef __bbtkData_h__
27 #define __bbtkData_h__
29 //#include "bbtkSystem.h"
30 //#include "bbtkMessageManager.h"
34 //#include "bbtkany.h"
36 //#include "bbtkReferenceCountedObject.h"
43 typedef any<thing> Data;
47 /// Can transport any kind of data (adaptation of boost::any)
57 template<typename ValueType>
58 Data(const ValueType & value)
59 : content(new holder<ValueType>(value))
63 Data(const Data & other)
64 : content(other.content ? other.content->clone() : 0)
75 Data & swap(Data & rhs)
77 std::swap(content, rhs.content);
81 template<typename ValueType>
82 Data & operator=(const ValueType & rhs)
84 Data(rhs).swap(*this);
88 Data & operator=(const Data & rhs)
90 Data(rhs).swap(*this);
101 const std::type_info & type() const
103 return content ? content->type() : typeid(void);
106 #ifndef BBTK_NO_MEMBER_TEMPLATE_FRIENDS
109 public: // types (public so Data_cast can be non-friend)
116 virtual ~placeholder()
122 virtual const std::type_info & type() const = 0;
124 virtual placeholder * clone() const = 0;
128 template<typename ValueType>
129 class holder : public placeholder
133 holder(const ValueType & value)
140 virtual const std::type_info & type() const
142 return typeid(ValueType);
145 virtual placeholder * clone() const
147 return new holder(held);
150 public: // representation
156 #ifndef BBTK_NO_MEMBER_TEMPLATE_FRIENDS
158 private: // representation
160 // template<typename ValueType>
161 // friend ValueType * Data_cast(Data *);
163 template<typename ValueType>
164 friend ValueType * unsafe_Data_cast(Data *);
166 template<typename ValueType>
167 friend ValueType unsafe_Data_cast(Data &);
171 public: // representation (public so Data_cast can be non-friend)
175 placeholder * content;
179 class bad_Data_cast : public std::bad_cast
182 virtual const char * what() const throw()
184 return "bbtk::bad_Data_cast: "
185 "failed conversion using bbtk::Data_cast";
190 template<typename ValueType>
191 ValueType * Data_cast(Data * operand)
193 return operand && operand->type() == typeid(ValueType)
194 ? &static_cast<Data::holder<ValueType> *>(operand->content)->held
198 template<typename ValueType>
199 const ValueType * Data_cast(const Data * operand)
201 return Data_cast<ValueType>(const_cast<Data *>(operand));
205 template<typename ValueType>
206 ValueType Data_cast(const Data & operand)
208 typedef BBTK_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
210 #ifdef BBTK_NO_TEMPLATE_PARTIAL_SPECIALIZATION
211 // If 'nonref' is still reference type, it means the user has not
212 // specialized 'remove_reference'.
214 // Please use BBTK_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
215 // to generate specialization of remove_reference for your class
216 // See type traits library documentation for details
217 BBTK_STATIC_ASSERT(!is_reference<nonref>::value);
220 const nonref * result = Data_cast<nonref>(&operand);
222 bbtk::throw_exception(bad_Data_cast());
226 template<typename ValueType>
227 ValueType Data_cast(Data & operand)
229 typedef BBTK_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
231 #ifdef BBTK_NO_TEMPLATE_PARTIAL_SPECIALIZATION
232 // The comment in the above version of 'Data_cast' explains when this
233 // assert is fired and what to do.
234 BBTK_STATIC_ASSERT(!is_reference<nonref>::value);
237 nonref * result = Data_cast<nonref>(&operand);
239 bbtk::throw_exception(bad_Data_cast());
243 // Note: The "unsafe" versions of Data_cast are not part of the
244 // public interface and may be removed at Data time. They are
245 // required where we know what type is stored in the Data and can't
246 // use typeid() comparison, e.g., when our types may travel across
247 // different shared libraries.
248 // LG : This is precisely our case !
250 template<typename ValueType>
251 inline ValueType * unsafe_Data_cast(Data * operand)
253 return &static_cast<Data::holder<ValueType> *>(operand->content)->held;
256 template<typename ValueType>
257 inline const ValueType * unsafe_Data_cast(const Data * operand)
259 return unsafe_Data_cast<ValueType>(const_cast<Data *>(operand));
262 template<typename ValueType>
263 inline ValueType unsafe_Data_cast(Data & operand)
265 return static_cast<Data::holder<ValueType> *>(operand.content)->held;
268 template<typename ValueType>
269 inline ValueType unsafe_Data_cast(const Data & operand)
271 return *unsafe_Data_cast<ValueType>(const_cast<Data *>(&operand));