Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
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
50
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
85namespace Teuchos {
86
87template<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
98template<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
109template <class T, class ok = typename is_comparable<T>::type>
110struct compare;
111
112template <class T>
113struct 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
123template <class T>
124struct compare<T, std::true_type> {
125 bool operator()(T const& a, T const& b) const {
126 return a == b;
127 }
128};
129
130template <class T, class ok = typename is_printable<T>::type>
131struct print;
132
133template <class T>
134struct 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
144template <class T>
145struct print<T, std::true_type> {
146 std::ostream& operator()(std::ostream& a, T const& b) const {
147 return a << b;
148 }
149};
150
155{
156public:
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
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
324public:
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
332private:
333
334 // /////////////////////////
335 // Private data members
336
337 placeholder * content;
338
339};
340
344class bad_any_cast : public std::runtime_error
345{
346public:
347 bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
348};
349
358template<typename ValueType>
359ValueType& 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
394template<typename ValueType>
395const ValueType& any_cast(const any &operand)
396{
397 return any_cast<ValueType>(const_cast<any&>(operand));
398}
399
403template <typename ValueType>
404ValueType* any_cast(any* operand)
405{
406 return &any_cast<ValueType>(*operand);
407}
408
412template <typename ValueType>
413ValueType 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
427template<typename ValueType>
428ValueType& any_ref_cast(any &operand)
429{
430 return Teuchos::any_cast<ValueType>(operand);
431}
432
438inline std::string toString(const any &rhs)
439{
440 std::ostringstream oss;
441 rhs.print(oss);
442 return oss.str();
443}
444
450inline bool operator==( const any &a, const any &b )
451{
452 return a.same(b);
453}
454
460inline bool operator!=( const any &a, const any &b )
461{
462 return !a.same(b);
463}
464
470inline std::ostream & operator<<(std::ostream & os, const any &rhs)
471{
472 rhs.print(os);
473 return os;
474}
475
479inline void swap(Teuchos::any& a, Teuchos::any& b) {
480 a.swap(b);
481}
482
486template <typename T>
488{
489 any(T()).swap(rhs);
490 return any_cast<T>(rhs);
491}
492
493} // namespace Teuchos
494
495#endif // TEUCHOS_ANY_HPP
#define TEUCHOSCORE_LIB_DLL_EXPORT
Defines basic traits returning the name of a type in a portable and readable way.
Modified boost::any class, which is a container for a templated value.
placeholder * content
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.
ValueType * any_cast(any *operand)
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.
ValueType any_cast(any &&operand)
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.
any(ValueType &&value)
Templated 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()
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.
bad_any_cast(const std::string msg)
#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.
bool operator()(T const &, T const &) const
bool operator()(T const &a, T const &b) const
static auto test(int) -> decltype(std::declval< X >()==std::declval< X >(), void(), std::true_type())
decltype(test< T >(0)) type
static auto test(...) -> std::false_type
static auto test(...) -> std::false_type
decltype(test< T >(0)) type
static auto test(int) -> decltype(std::declval< std::ostream & >()<< std::declval< X >(), void(), std::true_type())
std::ostream & operator()(std::ostream &s, T const &) const
std::ostream & operator()(std::ostream &a, T const &b) const