Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_any.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TEUCHOS_ANY_HPP
11 #define TEUCHOS_ANY_HPP
12 
17 #include <utility>
18 #include <type_traits>
19 #include <exception>
20 
21 #include "Teuchos_Assert.hpp"
23 #include "Teuchos_Exceptions.hpp"
24 
25 //
26 // This file was taken from the boost library which contained the
27 // following notice:
28 //
29 // *************************************************************
30 //
31 // what: variant type boost::any
32 // who: contributed by Kevlin Henney,
33 // with features contributed and bugs found by
34 // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
35 // when: July 2001
36 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
37 //
38 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
39 //
40 // Permission to use, copy, modify, and distribute this software for any
41 // purpose is hereby granted without fee, provided that this copyright and
42 // permissions notice appear in all copies and derivatives.
43 //
44 // This software is provided "as is" without express or implied warranty.
45 //
46 // *************************************************************
47 //
48 // RAB modified the file for use in Teuchos. I changed the nature of
49 // the any_cast<> to be easier to use.
50 //
51 
52 namespace Teuchos {
53 
54 template<class T>
55 struct is_comparable
56 {
57  template<class X>
58  static auto test(int) -> decltype(std::declval<X>() == std::declval<X>(),
59  void(), std::true_type());
60  template<class X>
61  static auto test(...) -> std::false_type;
62  using type = decltype(test<T>(0));
63 };
64 
65 template<class T>
66 struct is_printable
67 {
68  template<class X>
69  static auto test(int) -> decltype(std::declval<std::ostream&>() << std::declval<X>(),
70  void(), std::true_type());
71  template<class X>
72  static auto test(...) -> std::false_type;
73  using type = decltype(test<T>(0));
74 };
75 
76 template <class T, class ok = typename is_comparable<T>::type>
77 struct compare;
78 
79 template <class T>
80 struct compare<T, std::false_type> {
81  bool operator()(T const&, T const&) const {
82  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
83  "Trying to compare type " << typeid(T).name() << " which is not comparable");
84 #ifndef __CUDACC__
85  return false;
86 #endif
87  }
88 };
89 
90 template <class T>
91 struct compare<T, std::true_type> {
92  bool operator()(T const& a, T const& b) const {
93  return a == b;
94  }
95 };
96 
97 template <class T, class ok = typename is_printable<T>::type>
98 struct print;
99 
100 template <class T>
101 struct print<T, std::false_type> {
102  std::ostream& operator()(std::ostream& s, T const&) const {
103  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, NonprintableTypeException,
104  "Trying to print type " << Teuchos::demangleName(typeid(T).name()) <<
105  " which is not printable (i.e. does not have operator<<() defined)!");
106 #ifndef __CUDACC__
107  return s;
108 #endif
109  }
110 };
111 
112 template <class T>
113 struct print<T, std::true_type> {
114  std::ostream& operator()(std::ostream& a, T const& b) const {
115  return a << b;
116  }
117 };
118 
122 class TEUCHOSCORE_LIB_DLL_EXPORT any
123 {
124 public:
126  any()
127  : content(0)
128  {}
129 
131  template<typename ValueType>
132  explicit any(ValueType&& value)
133  : content(new holder<std::decay_t<ValueType>>(std::forward<ValueType>(value)))
134  {}
135 
137  any(const any & other)
138  : content(other.content ? other.content->clone() : 0)
139  {}
140 
142  any(any&& other)
143  : content(std::exchange(other.content,nullptr))
144  {}
145 
148  {
149  delete content;
150  }
151 
153  any & swap(any & rhs)
154  {
155  std::swap(content, rhs.content);
156  return *this;
157  }
158 
160  template<typename ValueType>
161  any & operator=(const ValueType & rhs)
162  {
163  any(rhs).swap(*this);
164  return *this;
165  }
166 
168  any & operator=(const any & rhs)
169  {
170  any(rhs).swap(*this);
171  return *this;
172  }
173 
175  any& operator=(any&& other)
176  {
177  if(this != &other) {
178  delete this->content;
179  this->content = std::exchange(other.content, nullptr);
180  }
181  return *this;
182  }
183 
185  TEUCHOS_DEPRECATED
186  bool empty() const
187  {
188  return ! this->has_value();
189  }
190 
192  bool has_value() const { return this->content != nullptr; }
193 
195  const std::type_info & type() const
196  {
197  return content ? content->type() : typeid(void);
198  }
199 
201  std::string typeName() const
202  {
203  return content ? content->typeName() : "NONE";
204  }
205 
210  bool same( const any &other ) const
211  {
212  if( !this->has_value() && !other.has_value() )
213  return true;
214  else if( this->has_value() && !other.has_value() )
215  return false;
216  else if( !this->has_value() && other.has_value() )
217  return false;
218  // this->has_value() && other.has_value()
219  return content->same(*other.content);
220  }
221 
226  void print(std::ostream& os) const
227  {
228  if (content) content->print(os);
229  }
230 
231 #ifndef DOXYGEN_SHOULD_SKIP_THIS
232 
234 
236  class placeholder
237  {
238  public:
240  virtual ~placeholder() {}
242  virtual const std::type_info & type() const = 0;
244  virtual std::string typeName() const = 0;
246  virtual placeholder * clone() const = 0;
248  virtual bool same( const placeholder &other ) const = 0;
250  virtual void print(std::ostream & os) const = 0;
251  };
252 
254  template<typename ValueType>
255  class holder : public placeholder
256  {
257  public:
259  template <typename U>
260  holder(U&& value)
261  : held(std::forward<U>(value))
262  {}
264  const std::type_info & type() const
265  { return typeid(ValueType); }
267  std::string typeName() const
268  { return TypeNameTraits<ValueType>::name(); }
270  placeholder * clone() const
271  { return new holder(held); }
273  bool same( const placeholder &other ) const
274  {
275  if( type() != other.type() ) {
276  return false;
277  }
278  // type() == other.type()
279  const ValueType
280  &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
281  return ::Teuchos::compare<ValueType>{}(held, other_held);
282  }
284  void print(std::ostream & os) const
285  { ::Teuchos::print<ValueType>{}(os, held); }
287  ValueType held;
288  };
289 
291 
292 public:
293  // Danger: This is made public to allow any_cast to be non-friend
294  placeholder* access_content()
295  { return content; }
296  const placeholder* access_content() const
297  { return content; }
298 #endif
299 
300 private:
301 
302  // /////////////////////////
303  // Private data members
304 
305  placeholder * content;
306 
307 };
308 
312 class bad_any_cast : public std::runtime_error
313 {
314 public:
315  bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
316 };
317 
326 template<typename ValueType>
327 ValueType& any_cast(any &operand)
328 {
329  const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
331  operand.type() != typeid(ValueType), bad_any_cast,
332  "any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
333  << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
334  << typeName(*operand.access_content()) << "!"
335  );
337  !operand.access_content(), bad_any_cast
338  ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
339  << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
340  );
341  any::holder<ValueType>
342  *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
344  !dyn_cast_content, std::logic_error
345  ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
346  << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
347  << typeName(*operand.access_content()) << "!"
348  << " The problem might be related to incompatible RTTI systems in static and shared libraries!"
349  );
350  return dyn_cast_content->held;
351 }
352 
362 template<typename ValueType>
363 const ValueType& any_cast(const any &operand)
364 {
365  return any_cast<ValueType>(const_cast<any&>(operand));
366 }
367 
371 template <typename ValueType>
372 ValueType* any_cast(any* operand)
373 {
374  return &any_cast<ValueType>(*operand);
375 }
376 
380 template <typename ValueType>
381 ValueType any_cast(any&& operand)
382 {
383  using U = std::remove_cv_t<std::remove_reference_t<ValueType>>;
384  static_assert(std::is_constructible_v<ValueType, U>);
385  return static_cast<ValueType>(std::move(*any_cast<U>(&operand)));
386 }
387 
395 template<typename ValueType>
396 ValueType& any_ref_cast(any &operand)
397 {
398  return Teuchos::any_cast<ValueType>(operand);
399 }
400 
406 inline std::string toString(const any &rhs)
407 {
408  std::ostringstream oss;
409  rhs.print(oss);
410  return oss.str();
411 }
412 
418 inline bool operator==( const any &a, const any &b )
419 {
420  return a.same(b);
421 }
422 
428 inline bool operator!=( const any &a, const any &b )
429 {
430  return !a.same(b);
431 }
432 
438 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
439 {
440  rhs.print(os);
441  return os;
442 }
443 
447 inline void swap(Teuchos::any& a, Teuchos::any& b) {
448  a.swap(b);
449 }
450 
454 template <typename T>
455 T & make_any_ref(any &rhs)
456 {
457  any(T()).swap(rhs);
458  return any_cast<T>(rhs);
459 }
460 
461 } // namespace Teuchos
462 
463 #endif // TEUCHOS_ANY_HPP
void print(std::ostream &os) const
Print this value to the output stream os
TEUCHOS_DEPRECATED bool empty() const
Return true if nothing is being stored.
T & make_any_ref(any &rhs)
Default constructs a new T value and returns a reference to it.
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.
bool has_value() const
Checks whether the object contains a value.
TEUCHOSCORE_LIB_DLL_EXPORT std::string demangleName(const std::string &mangledName)
Demangle a C++ name if valid.
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.
Modified boost::any class, which is a container for a templated value.
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.
ValueType & any_ref_cast(any &operand)
Keep the convenient behavior of Teuchos::any_cast w.r.t. references, but don&#39;t confuse it with the be...
any & operator=(const ValueType &rhs)
Copy the value rhs
any(ValueType &&value)
Templated constructor.
~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.
any & operator=(any &&other)
Move-assignment operator.
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.
void swap(Teuchos::any &a, Teuchos::any &b)
Special swap for other code to find via Argument Dependent Lookup.
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(any &&other)
Move constructor.
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 &quot;any&quot; input rhs to the output stream os.
#define TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.