Loading...
Searching...
No Matches
reference.h
Go to the documentation of this file.
1#ifndef _BBM_REFERENCE_H_
2#define _BBM_REFERENCE_H_
3
4#include <ostream>
5
6#include "core/error.h"
7#include "util/type_traits.h"
8#include "util/pointer.h"
9
10
11/***********************************************************************/
12/*! \file reference.h
13 \brief Assignable reference with wrapper support for rvalues
14************************************************************************/
15
16namespace bbm {
17
18 /*** Implementation details for reference_impl ***/
19 namespace detail {
20
21 template<typename T, typename PTR=std::add_pointer_t<std::remove_reference_t<T>>>
22 struct reference_impl
23 {
24 //! @{ \name constructors
25 inline constexpr reference_impl(std::nullptr_t = nullptr) noexcept : _ptr(nullptr) {}
26 inline constexpr reference_impl(std::add_lvalue_reference_t<T> ref) noexcept : _ptr(std::addressof(ref)) {}
27 inline constexpr reference_impl(const reference_impl& ref) noexcept = default;
28 //! @}
29
30 //! @{ \name assignment
31 inline constexpr reference_impl& operator=(const reference_impl& ref) noexcept = default;
32
33 template<typename R>
34 inline constexpr reference_impl& operator=(const R& val)
35 {
36 static_assert(!bbm::is_const_v<T>, BBM_CONST_ASSIGNMENT);
37 std::add_lvalue_reference_t<T>(*this) = val;
38 return *this;
39 }
40 //! @}
41
42 //! @{ \name cast operators
43 inline constexpr operator std::add_lvalue_reference_t<T>() const
44 {
45 if(!is_dereferenceable()) throw bbm_unassigned_ref;
46 return *_ptr;
47 }
48
49 template<typename TYPE> requires std::constructible_from<TYPE, T>
50 inline constexpr operator TYPE(void) const
51 {
52 if(!is_dereferenceable()) throw bbm_unassigned_ref;
53 return TYPE(*_ptr);
54 }
55 //! @}
56
57 //! \brief forward operator
58 inline constexpr PTR operator->(void) const { return _ptr; }
59
60 //! \brief check if dereferenceable
61 inline constexpr bool is_dereferenceable(void) const { return (_ptr != nullptr); }
62
63 //! \brief assign a new reference
64 template<typename R>
65 inline constexpr void reassign(R&& ref) noexcept { *this = reference_impl<T, PTR>(std::forward<R>(ref)); }
66
67 //! \brief ostream support
68 friend std::ostream& operator<<(std::ostream& s, const reference_impl<T,PTR>& ref)
69 {
70 if(ref.is_dereferenceable()) s << T(ref);
71 else s << "none";
72 return s;
73 }
74
75 protected:
76 PTR _ptr;
77 };
78
79 } // end detail namespace
80
81 /**********************************************************************/
82 /*! \brief Non-persistent reference (i.e., cannot take rvalues)
83 *********************************************************************/
84 template<typename T>
85 struct reference : public bbm::detail::reference_impl<T, std::add_pointer_t<std::remove_reference_t<T>>>
86 {
87 using base_type = bbm::detail::reference_impl<T, std::add_pointer_t<std::remove_reference_t<T>>>;
88 using base_type::base_type;
89 using base_type::operator=;
90
91 //! \brief Disallow rvalue construction
92 inline constexpr reference(std::decay_t<T>&& ) = delete;
93 };
94
95 //! \brief const non-persistent reference
96 template<typename T>
98
99 //! \brief Declaration of persistent_reference specialized below.
100 template<typename T> struct persistent_reference;
101
102 /**********************************************************************/
103 /*! \brief Persistent reference (no difference for non const references)
104 **********************************************************************/
105 template<typename T> requires (!bbm::is_const_v<T>)
107 {
108 using reference<T>::reference;
109 using reference<T>::operator=;
110 };
111
112 /**********************************************************************/
113 /*! \brief Persistent reference (extend lifetime of const rvalue references)
114 **********************************************************************/
115 template<typename T> requires bbm::is_const_v<T>
116 struct persistent_reference<T> : public bbm::detail::reference_impl<T, bbm::pointer<T>>
117 {
118 using base_type = bbm::detail::reference_impl<T, bbm::pointer<T>>;
119 using base_type::base_type;
120 using base_type::operator=;
121
122 //! \brief Handle assignment to a const reference of a temporary variable => make_pointer
123 //! This occurs if:
124 //! 1) R != persistent_reference<T> (use copy constructor in this case)
125 //! 2) if R == rvalue itself and R==T
126 //! else if an implicit conversion results in an rvalue (i.e., R is implicitely convertible to T and R!=T).
127 //! This explicitely avoids (non-rvalue) T
128 template<typename R> requires (!std::is_same_v<persistent_reference<T>, std::decay_t<R>>) &&
129 ((std::is_rvalue_reference_v<R&&> && std::same_as<std::remove_cvref_t<R>, std::remove_cvref_t<T>>) ||
130 (std::constructible_from<std::remove_reference_t<T>, R> && !std::same_as<std::remove_cvref_t<R>, std::remove_cvref_t<T>>))
131 inline constexpr persistent_reference(R&& val) noexcept
132 {
133 base_type::_ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<R>(val));
134 }
135 };
136
137 //! \brief const_persistent_reference
138 template<typename T>
140
141
142 /*** Implementation Details for is_bbm_reference ***/
143 namespace detail {
144 template<typename T> struct is_bbm_reference_impl : std::false_type {};
145 template<typename T, typename PTR> struct is_bbm_reference_impl<reference_impl<T,PTR>> : std::true_type {};
146 } // end detail namespace
147
148 /*********************************************************************/
149 /*! \@{ \name type traits
150 *********************************************************************/
151 template<typename T>
152 using is_bbm_reference = bbm::detail::is_bbm_reference_impl<std::decay_t<T>>;
153
154 template<typename T>
156 //! @}
157
158} // end bbm namespace
159
160
161#endif /* _BBM_REFERENCE_H_ */
Predefined exceptions for common errors.
#define bbm_unassigned_ref
Definition: error.h:43
#define BBM_CONST_ASSIGNMENT
Definition: error.h:54
Definition: aggregatebsdf.h:29
std::ostream & operator<<(std::ostream &s, const BSDF &bsdf)
Definition: bsdf_base.h:138
constexpr bool is_bbm_reference_v
Definition: reference.h:155
bbm::detail::is_bbm_reference_impl< std::decay_t< T > > is_bbm_reference
Definition: reference.h:152
Declaration of persistent_reference specialized below.
Definition: reference.h:100
Pointer wrapper that takes both shared and non-shared pointers. If the pointer is 'managed' then the ...
constexpr persistent_reference(R &&val) noexcept
Handle assignment to a const reference of a temporary variable => make_pointer This occurs if: 1) R !...
Definition: reference.h:131
bbm::detail::reference_impl< T, bbm::pointer< T > > base_type
Definition: reference.h:118
Non-persistent reference (i.e., cannot take rvalues)
Definition: reference.h:86
constexpr reference(std::decay_t< T > &&)=delete
Disallow rvalue construction.
bbm::detail::reference_impl< T, std::add_pointer_t< std::remove_reference_t< T > > > base_type
Definition: reference.h:87