@@ -46,6 +46,19 @@ struct default_constructible {
4646 };
4747};
4848
49+ struct immutable {
50+ template <typename >
51+ class modifier {
52+ public:
53+ modifier () noexcept = default ;
54+ modifier (const modifier&) = default ;
55+ modifier (modifier&&) = default ;
56+ ~modifier () = default ;
57+ modifier& operator =(const modifier&) = delete ;
58+ modifier& operator =(modifier&&) = delete ;
59+ };
60+ };
61+
4962namespace impl {
5063template <typename T>
5164constexpr bool supports_default_construction (
@@ -58,6 +71,18 @@ template<typename T, typename ... V>
5871using WhenConstructible = std::enable_if_t <std::is_constructible<T, V...>::value>;
5972}
6073
74+ namespace impl {
75+ template <typename T>
76+ constexpr bool is_immutable (const ::strong::immutable::modifier<T>*)
77+ {
78+ return true ;
79+ }
80+ constexpr bool is_immutable (const void *)
81+ {
82+ return false ;
83+ }
84+ }
85+
6186template <typename T, typename Tag, typename ... M>
6287class type : public modifier <M, type<T, Tag, M...>> ... {
6388public:
@@ -109,32 +134,36 @@ class type : public modifier<M, type<T, Tag, M...>> ... {
109134 swap (a._val , b._val );
110135 }
111136
137+ template <typename type_ = type>
112138 STRONG_NODISCARD
113- constexpr T & value_of () & noexcept
139+ constexpr std:: enable_if_t <!impl::is_immutable( static_cast <type_*>( nullptr )), T&> value_of () & noexcept
114140 { return _val; }
115141
116142 STRONG_NODISCARD
117143 constexpr const T &value_of () const & noexcept
118144 { return _val; }
119145
146+ template <typename type_ = type>
120147 STRONG_NODISCARD
121- constexpr T && value_of() && noexcept
148+ constexpr std:: enable_if_t <!impl::is_immutable( static_cast <type_*>( nullptr )), T&&> value_of () && noexcept
122149 { return std::move (_val); }
123150
124151 STRONG_NODISCARD
125152 constexpr const T &&value_of() const && noexcept
126153 { return std::move (_val); }
127154
155+ template <typename type_ = type>
128156 STRONG_NODISCARD
129- friend constexpr T & value_of (type &t) noexcept
157+ friend constexpr auto value_of (type &t) noexcept -> std::enable_if_t<!impl::is_immutable( static_cast <type_*>( nullptr )), T&>
130158 { return t._val ; }
131159
132160 STRONG_NODISCARD
133161 friend constexpr const T &value_of (const type &t) noexcept
134162 { return t._val ; }
135163
164+ template <typename type_ = type>
136165 STRONG_NODISCARD
137- friend constexpr T && value_of(type &&t) noexcept
166+ friend constexpr auto value_of (type &&t) noexcept -> std::enable_if_t<!impl::is_immutable( static_cast <type_*>( nullptr )), T&&>
138167 { return std::move (t)._val ; }
139168
140169 STRONG_NODISCARD
0 commit comments