guanaqo 1.0.0-alpha.27
Utilities for scientific software
Loading...
Searching...
No Matches
any-ptr.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @ingroup type_erasure
5/// Non-owning and shared pointer wrappers with type tagging.
6
7#include <any>
8#include <memory>
9#include <type_traits>
10#include <typeinfo>
11
12namespace guanaqo {
13
14/// Like std::any, but storing just the pointer, without any dynamic allocation.
15/// @ingroup type_erasure
16class any_ptr {
17 public:
18 any_ptr() = default;
19 template <class T>
20 any_ptr(T *ptr) noexcept
21 : ptr{const_cast<void *>(reinterpret_cast<const void *>(ptr))},
22 ptr_type{&typeid(T)}, is_const{std::is_const_v<T>} {}
23
24 template <class T>
25 T *cast() const {
26 if (!ptr)
27 return nullptr;
28 if (typeid(T) != type())
29 throw std::bad_any_cast();
30 if (std::is_const_v<T> != is_const)
31 throw std::bad_any_cast();
32 return reinterpret_cast<T *>(ptr);
33 }
34
35 [[nodiscard]] bool has_value() const noexcept { return ptr != nullptr; }
36 [[nodiscard]] bool is_immutable() const noexcept { return is_const; }
37 [[nodiscard]] const std::type_info &type() const noexcept {
38 return *ptr_type;
39 }
40
41 private:
42 void *ptr = nullptr;
43 const std::type_info *ptr_type = &typeid(void);
44 bool is_const = true;
45};
46
47/// Like std::any, but storing a shared_ptr, to allow for move-only types.
48/// @ingroup type_erasure
50 public:
51 shared_any_ptr() = default;
52 template <class T>
53 shared_any_ptr(std::shared_ptr<T> ptr) noexcept
54 : ptr{std::move(ptr),
55 const_cast<void *>(reinterpret_cast<const void *>(ptr.get()))},
56 ptr_type{&typeid(T)}, is_const{std::is_const_v<T>} {}
57 shared_any_ptr(const shared_any_ptr &) = default;
58 shared_any_ptr(shared_any_ptr &&) noexcept = default;
59 shared_any_ptr &operator=(const shared_any_ptr &) = default;
60 shared_any_ptr &operator=(shared_any_ptr &&) noexcept = default;
61
62 template <class T>
63 T *cast() const {
64 if (!ptr)
65 return nullptr;
66 if (typeid(T) != type())
67 throw std::bad_any_cast();
68 if (std::is_const_v<T> != is_const)
69 throw std::bad_any_cast();
70 return reinterpret_cast<T *>(ptr.get());
71 }
72
73 [[nodiscard]] bool has_value() const noexcept { return bool{ptr}; }
74 [[nodiscard]] bool is_immutable() const noexcept { return is_const; }
75 [[nodiscard]] const std::type_info &type() const noexcept {
76 return *ptr_type;
77 }
78
79 private:
80 std::shared_ptr<void> ptr;
81 const std::type_info *ptr_type = &typeid(void);
82 bool is_const = true;
83};
84
85} // namespace guanaqo
bool is_immutable() const noexcept
Definition any-ptr.hpp:36
T * cast() const
Definition any-ptr.hpp:25
const std::type_info * ptr_type
Definition any-ptr.hpp:43
any_ptr(T *ptr) noexcept
Definition any-ptr.hpp:20
const std::type_info & type() const noexcept
Definition any-ptr.hpp:37
bool has_value() const noexcept
Definition any-ptr.hpp:35
any_ptr()=default
bool has_value() const noexcept
Definition any-ptr.hpp:73
const std::type_info * ptr_type
Definition any-ptr.hpp:81
shared_any_ptr(std::shared_ptr< T > ptr) noexcept
Definition any-ptr.hpp:53
shared_any_ptr(const shared_any_ptr &)=default
const std::type_info & type() const noexcept
Definition any-ptr.hpp:75
shared_any_ptr(shared_any_ptr &&) noexcept=default
bool is_immutable() const noexcept
Definition any-ptr.hpp:74
std::shared_ptr< void > ptr
Definition any-ptr.hpp:80