Ditto 4.13.1
 
Loading...
Searching...
No Matches
any.hpp
1#ifndef DITTO_ANY_H
2#define DITTO_ANY_H
3
4#include <memory>
5
9namespace ditto {
10
18class any {
19private:
20 struct VirtualBase {
21 virtual ~VirtualBase() noexcept = default;
22 virtual std::type_info const &virtual_type() const noexcept = 0;
23 virtual std::unique_ptr<VirtualBase> virtual_clone() const noexcept = 0;
24
25 template <typename T>
26 static std::unique_ptr<VirtualBase> upcast(T const &value) noexcept {
27 return std::unique_ptr<VirtualBase>(new ConcreteType<T>(value));
28 }
29 };
30
31 // main field of `any`:
32 std::unique_ptr<VirtualBase> erased_value;
33
34 // helper to go from `<T>` to `VirtualBase`.
35 template <typename T> struct ConcreteType : VirtualBase {
36 T value;
37
38 explicit ConcreteType(T const &val) noexcept : value(val) {}
39
40 std::type_info const &virtual_type() const noexcept override {
41 return typeid(T);
42 }
43
44 std::unique_ptr<VirtualBase> virtual_clone() const noexcept override {
45 return any::VirtualBase::upcast(value);
46 }
47 };
48
49 template <typename T> friend T any_cast(ditto::any const &operand);
50
51public:
52 any() noexcept;
53
54 // TOOD(kj): C++ guidelines recommend using `explicit` for single-arg
55 // constructors to avoid unexpected implicit conversions. However, our
56 // AnyHelpers functions currently rely on implicit conversion, so we are
57 // intentionally not using `explicit` here. We should look into whether there
58 // is a safer way to do what we are doing.
59 template <typename T>
60 any(T const &value) noexcept // NOLINT
61 : erased_value(any::VirtualBase::upcast(value)) {}
62
63 any(any const &other) noexcept;
64
65 void swap(any &other) noexcept;
66
67 any &operator=(any const &other) noexcept;
68
69 std::type_info const &type() const noexcept;
70
71 bool has_value() const noexcept;
72
73 template <typename T> T as() const {
74 if (auto ptr =
75 dynamic_cast<any::ConcreteType<T> const *>(erased_value.get())) {
76 return ptr->value;
77 }
78 throw std::bad_cast();
79 }
80};
81
82template <typename T> T any_cast(ditto::any const &operand) {
83 return operand.as<T>();
84}
85
86} // namespace ditto
87
88#endif
Polyfill of std::any for C++11.
Definition any.hpp:18
Namespace for the Ditto C++ SDK types and functions.
Definition AbstractDocumentPath.hpp:19