Teuchos Package Browser (Single Doxygen Collection)  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 /*
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 <utility>
52 #include <type_traits>
53 #include <exception>
54 
55 #include "Teuchos_Assert.hpp"
57 
58 //
59 // This file was taken from the boost library which contained the
60 // following notice:
61 //
62 // *************************************************************
63 //
64 // what: variant type boost::any
65 // who: contributed by Kevlin Henney,
66 // with features contributed and bugs found by
67 // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
68 // when: July 2001
69 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
70 //
71 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
72 //
73 // Permission to use, copy, modify, and distribute this software for any
74 // purpose is hereby granted without fee, provided that this copyright and
75 // permissions notice appear in all copies and derivatives.
76 //
77 // This software is provided "as is" without express or implied warranty.
78 //
79 // *************************************************************
80 //
81 // RAB modified the file for use in Teuchos. I changed the nature of
82 // the any_cast<> to be easier to use.
83 //
84 
85 namespace Teuchos {
86 
87 template<class T>
89 {
90  template<class X>
91  static auto test(int) -> decltype(std::declval<X>() == std::declval<X>(),
92  void(), std::true_type());
93  template<class X>
94  static auto test(...) -> std::false_type;
95  using type = decltype(test<T>(0));
96 };
97 
98 template<class T>
100 {
101  template<class X>
102  static auto test(int) -> decltype(std::declval<std::ostream&>() << std::declval<X>(),
103  void(), std::true_type());
104  template<class X>
105  static auto test(...) -> std::false_type;
106  using type = decltype(test<T>(0));
107 };
108 
109 template <class T, class ok = typename is_comparable<T>::type>
110 struct compare;
111 
112 template <class T>
113 struct compare<T, std::false_type> {
114  bool operator()(T const&, T const&) const {
115  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
116  "Trying to compare type " << typeid(T).name() << " which is not comparable");
117 #ifndef __CUDACC__
118  return false;
119 #endif
120  }
121 };
122 
123 template <class T>
124 struct compare<T, std::true_type> {
125  bool operator()(T const& a, T const& b) const {
126  return a == b;
127  }
128 };
129 
130 template <class T, class ok = typename is_printable<T>::type>
131 struct print;
132 
133 template <class T>
134 struct print<T, std::false_type> {
135  std::ostream& operator()(std::ostream& s, T const&) const {
136  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
137  "Trying to print type " << typeid(T).name() << " which is not printable");
138 #ifndef __CUDACC__
139  return s;
140 #endif
141  }
142 };
143 
144 template <class T>
145 struct print<T, std::true_type> {
146  std::ostream& operator()(std::ostream& a, T const& b) const {
147  return a << b;
148  }
149 };
150 
155 {
156 public:
158  any()
159  : content(0)
160  {}
161 
163  template<typename ValueType>
164  explicit any(ValueType&& value)
165  : content(new holder<std::decay_t<ValueType>>(std::forward<ValueType>(value)))
166  {}
167 
169  any(const any & other)
170  : content(other.content ? other.content->clone() : 0)
171  {}
172 
174  any(any&& other)
175  : content(std::exchange(other.content,nullptr))
176  {}
177 
180  {
181  delete content;
182  }
183 
185  any & swap(any & rhs)
186  {
187  std::swap(content, rhs.content);
188  return *this;
189  }
190 
192  template<typename ValueType>
193  any & operator=(const ValueType & rhs)
194  {
195  any(rhs).swap(*this);
196  return *this;
197  }
198 
200  any & operator=(const any & rhs)
201  {
202  any(rhs).swap(*this);
203  return *this;
204  }
205 
207  any& operator=(any&& other)
208  {
209  if(this != &other) {
210  delete this->content;
211  this->content = std::exchange(other.content, nullptr);
212  }
213  return *this;
214  }
215 
217  TEUCHOS_DEPRECATED
218  bool empty() const
219  {
220  return ! this->has_value();
221  }
222 
224  bool has_value() const { return this->content != nullptr; }
225 
227  const std::type_info & type() const
228  {
229  return content ? content->type() : typeid(void);
230  }
231 
233  std::string typeName() const
234  {
235  return content ? content->typeName() : "NONE";
236  }
237 
242  bool same( const any &other ) const
243  {
244  if( !this->has_value() && !other.has_value() )
245  return true;
246  else if( this->has_value() && !other.has_value() )
247  return false;
248  else if( !this->has_value() && other.has_value() )
249  return false;
250  // this->has_value() && other.has_value()
251  return content->same(*other.content);
252  }
253 
258  void print(std::ostream& os) const
259  {
260  if (content) content->print(os);
261  }
262 
263 #ifndef DOXYGEN_SHOULD_SKIP_THIS
264 
266 
268  class placeholder
269  {
270  public:
272  virtual ~placeholder() {}
274  virtual const std::type_info & type() const = 0;
276  virtual std::string typeName() const = 0;
278  virtual placeholder * clone() const = 0;
280  virtual bool same( const placeholder &other ) const = 0;
282  virtual void print(std::ostream & os) const = 0;
283  };
284 
286  template<typename ValueType>
287  class holder : public placeholder
288  {
289  public:
291  template <typename U>
292  holder(U&& value)
293  : held(std::forward<U>(value))
294  {}
296  const std::type_info & type() const
297  { return typeid(ValueType); }
299  std::string typeName() const
300  { return TypeNameTraits<ValueType>::name(); }
302  placeholder * clone() const
303  { return new holder(held); }
305  bool same( const placeholder &other ) const
306  {
307  if( type() != other.type() ) {
308  return false;
309  }
310  // type() == other.type()
311  const ValueType
312  &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
313  return ::Teuchos::compare<ValueType>{}(held, other_held);
314  }
316  void print(std::ostream & os) const
317  { ::Teuchos::print<ValueType>{}(os, held); }
319  ValueType held;
320  };
321 
323 
324 public:
325  // Danger: This is made public to allow any_cast to be non-friend
326  placeholder* access_content()
327  { return content; }
328  const placeholder* access_content() const
329  { return content; }
330 #endif
331 
332 private:
333 
334  // /////////////////////////
335  // Private data members
336 
337  placeholder * content;
338 
339 };
340 
344 class bad_any_cast : public std::runtime_error
345 {
346 public:
347  bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
348 };
349 
358 template<typename ValueType>
359 ValueType& any_cast(any &operand)
360 {
361  const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
363  operand.type() != typeid(ValueType), bad_any_cast,
364  "any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
365  << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
366  << typeName(*operand.access_content()) << "!"
367  );
369  !operand.access_content(), bad_any_cast
370  ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
371  << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
372  );
373  any::holder<ValueType>
374  *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
376  !dyn_cast_content, std::logic_error
377  ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
378  << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
379  << typeName(*operand.access_content()) << "!"
380  << " The problem might be related to incompatible RTTI systems in static and shared libraries!"
381  );
382  return dyn_cast_content->held;
383 }
384 
394 template<typename ValueType>
395 const ValueType& any_cast(const any &operand)
396 {
397  return any_cast<ValueType>(const_cast<any&>(operand));
398 }
399 
403 template <typename ValueType>
404 ValueType* any_cast(any* operand)
405 {
406  return &any_cast<ValueType>(*operand);
407 }
408 
412 template <typename ValueType>
413 ValueType any_cast(any&& operand)
414 {
415  using U = std::remove_cv_t<std::remove_reference_t<ValueType>>;
416  static_assert(std::is_constructible_v<ValueType, U>);
417  return static_cast<ValueType>(std::move(*any_cast<U>(&operand)));
418 }
419 
427 template<typename ValueType>
428 ValueType& any_ref_cast(any &operand)
429 {
430  return Teuchos::any_cast<ValueType>(operand);
431 }
432 
438 inline std::string toString(const any &rhs)
439 {
440  std::ostringstream oss;
441  rhs.print(oss);
442  return oss.str();
443 }
444 
450 inline bool operator==( const any &a, const any &b )
451 {
452  return a.same(b);
453 }
454 
460 inline bool operator!=( const any &a, const any &b )
461 {
462  return !a.same(b);
463 }
464 
470 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
471 {
472  rhs.print(os);
473  return os;
474 }
475 
479 inline void swap(Teuchos::any& a, Teuchos::any& b) {
480  a.swap(b);
481 }
482 
486 template <typename T>
487 T & make_any_ref(any &rhs)
488 {
489  any(T()).swap(rhs);
490  return any_cast<T>(rhs);
491 }
492 
493 } // namespace Teuchos
494 
495 #endif // TEUCHOS_ANY_HPP
bool operator()(T const &a, T const &b) const
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.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
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.
bool operator()(T const &, T const &) const
decltype(test< T >(0)) type
Definition: Teuchos_any.hpp:95
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.
static auto test(int) -> decltype(std::declval< std::ostream & >()<< std::declval< X >(), void(), std::true_type())
#define TEUCHOSCORE_LIB_DLL_EXPORT
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
ValueType * any_cast(any *operand)
any(ValueType &&value)
Templated constructor.
ValueType any_cast(any &&operand)
bad_any_cast(const std::string msg)
~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.
std::ostream & operator()(std::ostream &s, T const &) const
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.
std::ostream & operator()(std::ostream &a, T const &b) const
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
static auto test(int) -> decltype(std::declval< X >()==std::declval< X >(), void(), std::true_type())
any(any &&other)
Move constructor.
decltype(test< T >(0)) type
any(const any &other)
Copy constructor.
placeholder * content
std::ostream & operator<<(std::ostream &os, const any &rhs)
Writes &quot;any&quot; input rhs to the output stream os.