Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_any.hpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Teuchos: Common Tools Package
6 // Copyright (2004) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 */
43 
44 #ifndef TEUCHOS_ANY_HPP
45 #define TEUCHOS_ANY_HPP
46 
51 #include "Teuchos_Assert.hpp"
53 
54 //
55 // This file was taken from the boost library which contained the
56 // following notice:
57 //
58 // *************************************************************
59 //
60 // what: variant type boost::any
61 // who: contributed by Kevlin Henney,
62 // with features contributed and bugs found by
63 // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
64 // when: July 2001
65 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
66 //
67 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
68 //
69 // Permission to use, copy, modify, and distribute this software for any
70 // purpose is hereby granted without fee, provided that this copyright and
71 // permissions notice appear in all copies and derivatives.
72 //
73 // This software is provided "as is" without express or implied warranty.
74 //
75 // *************************************************************
76 //
77 // RAB modified the file for use in Teuchos. I changed the nature of
78 // the any_cast<> to be easier to use.
79 //
80 
81 namespace Teuchos {
82 
86 class TEUCHOSCORE_LIB_DLL_EXPORT any
87 {
88 public:
90  any()
91  : content(0)
92  {}
93 
95  template<typename ValueType>
96  explicit any(const ValueType & value)
97  : content(new holder<ValueType>(value))
98  {}
99 
101  any(const any & other)
102  : content(other.content ? other.content->clone() : 0)
103  {}
104 
107  {
108  delete content;
109  }
110 
112  any & swap(any & rhs)
113  {
114  std::swap(content, rhs.content);
115  return *this;
116  }
117 
119  template<typename ValueType>
120  any & operator=(const ValueType & rhs)
121  {
122  any(rhs).swap(*this);
123  return *this;
124  }
125 
127  any & operator=(const any & rhs)
128  {
129  any(rhs).swap(*this);
130  return *this;
131  }
132 
134  bool empty() const
135  {
136  return !content;
137  }
138 
140  const std::type_info & type() const
141  {
142  return content ? content->type() : typeid(void);
143  }
144 
146  std::string typeName() const
147  {
148  return content ? content->typeName() : "NONE";
149  }
150 
152  bool same( const any &other ) const
153  {
154  if( this->empty() && other.empty() )
155  return true;
156  else if( this->empty() && !other.empty() )
157  return false;
158  else if( !this->empty() && other.empty() )
159  return false;
160  // !this->empty() && !other.empty()
161  return content->same(*other.content);
162  }
163 
165  void print(std::ostream& os) const
166  {
167  if (content) content->print(os);
168  }
169 
170 #ifndef DOXYGEN_SHOULD_SKIP_THIS
171 
173 
175  class placeholder
176  {
177  public:
179  virtual ~placeholder() {}
181  virtual const std::type_info & type() const = 0;
183  virtual std::string typeName() const = 0;
185  virtual placeholder * clone() const = 0;
187  virtual bool same( const placeholder &other ) const = 0;
189  virtual void print(std::ostream & os) const = 0;
190  };
191 
193  template<typename ValueType>
194  class holder : public placeholder
195  {
196  public:
198  holder(const ValueType & value)
199  : held(value)
200  {}
202  const std::type_info & type() const
203  { return typeid(ValueType); }
205  std::string typeName() const
206  { return TypeNameTraits<ValueType>::name(); }
208  placeholder * clone() const
209  { return new holder(held); }
211  bool same( const placeholder &other ) const
212  {
213  if( type() != other.type() ) {
214  return false;
215  }
216  // type() == other.type()
217  const ValueType
218  &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
219  return held == other_held;
220  }
222  void print(std::ostream & os) const
223  { os << held; }
225  ValueType held;
226  };
227 
229 
230 public:
231  // Danger: This is made public to allow any_cast to be non-friend
232  placeholder* access_content()
233  { return content; }
234  const placeholder* access_content() const
235  { return content; }
236 #endif
237 
238 private:
239 
240  // /////////////////////////
241  // Private data members
242 
243  placeholder * content;
244 
245 };
246 
250 class bad_any_cast : public std::runtime_error
251 {
252 public:
253  bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
254 };
255 
264 template<typename ValueType>
265 ValueType& any_cast(any &operand)
266 {
267  const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
269  operand.type() != typeid(ValueType), bad_any_cast,
270  "any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
271  << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
272  << typeName(*operand.access_content()) << "!"
273  );
275  !operand.access_content(), bad_any_cast
276  ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
277  << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
278  );
279  any::holder<ValueType>
280  *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
282  !dyn_cast_content, std::logic_error
283  ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
284  << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
285  << typeName(*operand.access_content()) << "!"
286  << " The problem might be related to incompatible RTTI systems in static and shared libraries!"
287  );
288  return dyn_cast_content->held;
289 }
290 
300 template<typename ValueType>
301 const ValueType& any_cast(const any &operand)
302 {
303  return any_cast<ValueType>(const_cast<any&>(operand));
304 }
305 
309 inline std::string toString(const any &rhs)
310 {
311  std::ostringstream oss;
312  rhs.print(oss);
313  return oss.str();
314 }
315 
319 inline bool operator==( const any &a, const any &b )
320 {
321  return a.same(b);
322 }
323 
327 inline bool operator!=( const any &a, const any &b )
328 {
329  return !a.same(b);
330 }
331 
335 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
336 {
337  rhs.print(os);
338  return os;
339 }
340 
341 } // namespace Teuchos
342 
343 #endif // TEUCHOS_ANY_HPP
void print(std::ostream &os) const
Print this value to the output stream os
bool same(const any &other) const
Return if two any objects are the same or not.
ValueType & any_cast(any &operand)
Used to extract the templated value held in Teuchos::any to a given value type.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
const ValueType & any_cast(const any &operand)
Used to extract the const templated value held in Teuchos::any to a given const value type...
any()
Empty constructor.
Definition: Teuchos_any.hpp:90
Modified boost::any class, which is a container for a templated value.
Definition: Teuchos_any.hpp:86
any & swap(any &rhs)
Method for swapping the contents of two any classes.
std::string toString(const any &rhs)
Converts the value in any to a std::string.
Thrown if any_cast is attempted between two incompatable types.
any & operator=(const ValueType &rhs)
Copy the value rhs
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
~any()
Destructor.
bool operator==(const any &a, const any &b)
Returns true if two any objects have the same value.
std::string typeName() const
Return the name of the type.
const std::type_info & type() const
Return the type of value being stored.
bool operator!=(const any &a, const any &b)
Returns true if two any objects do not have the same value.
Defines basic traits returning the name of a type in a portable and readable way. ...
any & operator=(const any &rhs)
Copy the value held in rhs
any(const ValueType &value)
Templated constructor.
Definition: Teuchos_any.hpp:96
any(const any &other)
Copy constructor.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
std::ostream & operator<<(std::ostream &os, const any &rhs)
Writes "any" input rhs to the output stream os.
bool empty() const
Return true if nothing is being stored.