Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
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
52namespace Teuchos {
53
54template<class T>
55struct 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
65template<class T>
66struct 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
76template <class T, class ok = typename is_comparable<T>::type>
77struct compare;
78
79template <class T>
80struct 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
90template <class T>
91struct compare<T, std::true_type> {
92 bool operator()(T const& a, T const& b) const {
93 return a == b;
94 }
95};
96
97template <class T, class ok = typename is_printable<T>::type>
98struct print;
99
100template <class T>
101struct 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
112template <class T>
113struct print<T, std::true_type> {
114 std::ostream& operator()(std::ostream& a, T const& b) const {
115 return a << b;
116 }
117};
118
122class TEUCHOSCORE_LIB_DLL_EXPORT any
123{
124public:
127 : content(0)
128 {}
129
131 template<typename ValueType,
132 std::enable_if_t<!std::is_same_v<std::decay_t<ValueType>, any>, int> = 0>
133 explicit any(ValueType&& value)
134 : content(new holder<std::decay_t<ValueType>>(std::forward<ValueType>(value)))
135 {}
136
138 any(const any & other)
139 : content(other.content ? other.content->clone() : 0)
140 {}
141
143 any(any&& other)
144 : content(std::exchange(other.content,nullptr))
145 {}
146
149 {
150 delete content;
151 }
152
154 any & swap(any & rhs)
155 {
156 std::swap(content, rhs.content);
157 return *this;
158 }
159
161 template<typename ValueType>
162 any & operator=(const ValueType & rhs)
163 {
164 any(rhs).swap(*this);
165 return *this;
166 }
167
169 any & operator=(const any & rhs)
170 {
171 any(rhs).swap(*this);
172 return *this;
173 }
174
176 any& operator=(any&& other)
177 {
178 if(this != &other) {
179 delete this->content;
180 this->content = std::exchange(other.content, nullptr);
181 }
182 return *this;
183 }
184
187 bool empty() const
188 {
189 return ! this->has_value();
190 }
191
193 bool has_value() const { return this->content != nullptr; }
194
196 const std::type_info & type() const
197 {
198 return content ? content->type() : typeid(void);
199 }
200
202 std::string typeName() const
203 {
204 return content ? content->typeName() : "NONE";
205 }
206
211 bool same( const any &other ) const
212 {
213 if( !this->has_value() && !other.has_value() )
214 return true;
215 else if( this->has_value() && !other.has_value() )
216 return false;
217 else if( !this->has_value() && other.has_value() )
218 return false;
219 // this->has_value() && other.has_value()
220 return content->same(*other.content);
221 }
222
227 void print(std::ostream& os) const
228 {
229 if (content) content->print(os);
230 }
231
232#ifndef DOXYGEN_SHOULD_SKIP_THIS
235
237 class placeholder
238 {
239 public:
241 virtual ~placeholder() {}
243 virtual const std::type_info & type() const = 0;
245 virtual std::string typeName() const = 0;
247 virtual placeholder * clone() const = 0;
249 virtual bool same( const placeholder &other ) const = 0;
251 virtual void print(std::ostream & os) const = 0;
252 };
253
255 template<typename ValueType>
256 class holder : public placeholder
257 {
258 public:
260 template <typename U>
261 holder(U&& value)
262 : held(std::forward<U>(value))
263 {}
265 const std::type_info & type() const
266 { return typeid(ValueType); }
268 std::string typeName() const
269 { return TypeNameTraits<ValueType>::name(); }
271 placeholder * clone() const
272 { return new holder(held); }
274 bool same( const placeholder &other ) const
275 {
276 if( type() != other.type() ) {
277 return false;
278 }
279 // type() == other.type()
280 const ValueType
281 &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
282 return ::Teuchos::compare<ValueType>{}(held, other_held);
283 }
285 void print(std::ostream & os) const
286 { ::Teuchos::print<ValueType>{}(os, held); }
288 ValueType held;
289 };
290
292
293public:
294 // Danger: This is made public to allow any_cast to be non-friend
295 placeholder* access_content()
296 { return content; }
297 const placeholder* access_content() const
298 { return content; }
299#endif
300
301private:
302
303 // /////////////////////////
304 // Private data members
305
306 placeholder * content;
307
308};
309
313class bad_any_cast : public std::runtime_error
314{
315public:
316 bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
317};
318
327template<typename ValueType>
329{
332 operand.type() != typeid(ValueType), bad_any_cast,
333 "any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
334 << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
335 << typeName(*operand.access_content()) << "!"
336 );
338 !operand.access_content(), bad_any_cast
339 ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
340 << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
341 );
342 any::holder<ValueType>
343 *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
345 !dyn_cast_content, std::logic_error
346 ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
347 << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
348 << typeName(*operand.access_content()) << "!"
349 << " The problem might be related to incompatible RTTI systems in static and shared libraries!"
350 );
351 return dyn_cast_content->held;
352}
353
363template<typename ValueType>
365{
366 return any_cast<ValueType>(const_cast<any&>(operand));
367}
368
372template <typename ValueType>
373ValueType* any_cast(any* operand)
374{
376}
377
381template <typename ValueType>
382ValueType any_cast(any&& operand)
383{
384 using U = std::remove_cv_t<std::remove_reference_t<ValueType>>;
385 static_assert(std::is_constructible_v<ValueType, U>);
386 return static_cast<ValueType>(std::move(*any_cast<U>(&operand)));
387}
388
396template<typename ValueType>
401
407inline std::string toString(const any &rhs)
408{
409 std::ostringstream oss;
410 rhs.print(oss);
411 return oss.str();
412}
413
419inline bool operator==( const any &a, const any &b )
420{
421 return a.same(b);
422}
423
429inline bool operator!=( const any &a, const any &b )
430{
431 return !a.same(b);
432}
433
439inline std::ostream & operator<<(std::ostream & os, const any &rhs)
440{
441 rhs.print(os);
442 return os;
443}
444
449 a.swap(b);
450}
451
455template <typename T>
457{
458 any(T()).swap(rhs);
459 return any_cast<T>(rhs);
460}
461
462} // namespace Teuchos
463
464#endif // TEUCHOS_ANY_HPP
Defines basic traits returning the name of a type in a portable and readable way.
Smart reference counting pointer class for automatic garbage collection.
void swap(RCP< T > &r_ptr)
Swap the contents with some other RCP object.
Modified boost::any class, which is a container for a templated value.
void print(std::ostream &os) const
Print this value to the output stream os
std::string toString(const any &rhs)
Converts the value in any to a std::string.
any & operator=(any &&other)
Move-assignment operator.
bool operator==(const any &a, const any &b)
Returns true if two any objects have the same value.
bool same(const any &other) const
Return if two any objects are the same or not.
std::ostream & operator<<(std::ostream &os, const any &rhs)
Writes "any" input rhs to the output stream os.
const ValueType & any_cast(const any &operand)
Used to extract the const templated value held in Teuchos::any to a given const value type.
bool operator!=(const any &a, const any &b)
Returns true if two any objects do not have the same value.
ValueType & any_cast(any &operand)
Used to extract the templated value held in Teuchos::any to a given value type.
TEUCHOS_DEPRECATED bool empty() const
Return true if nothing is being stored.
void swap(Teuchos::any &a, Teuchos::any &b)
Special swap for other code to find via Argument Dependent Lookup.
any(any &&other)
Move constructor.
any(const any &other)
Copy constructor.
std::string typeName() const
Return the name of the type.
~any()
Destructor.
const std::type_info & type() const
Return the type of value being stored.
ValueType & any_ref_cast(any &operand)
Keep the convenient behavior of Teuchos::any_cast w.r.t. references, but don't confuse it with the be...
any(ValueType &&value)
Templated constructor (excluded for any/any& to prevent infinite recursion via holder<any>)
any()
Empty constructor.
T & make_any_ref(any &rhs)
Default constructs a new T value and returns a reference to it.
any & swap(any &rhs)
Method for swapping the contents of two any classes.
bool has_value() const
Checks whether the object contains a value.
any & operator=(const ValueType &rhs)
Copy the value rhs
any & operator=(const any &rhs)
Copy the value held in rhs
Thrown if any_cast is attempted between two incompatable types.
#define TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
TEUCHOSCORE_LIB_DLL_EXPORT std::string demangleName(const std::string &mangledName)
Demangle a C++ name if valid.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...