Skip to content

Commit 6a1328a

Browse files
committed
[optional] Add support for reference_wrapper in just()
1 parent 0d10090 commit 6a1328a

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

include/boost/hana/fwd/optional.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ BOOST_HANA_NAMESPACE_BEGIN
269269
//! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
270270
//! for consistency with the other `make<...>` functions.
271271
//!
272+
//! @note
273+
//! `make<optional_tag>` supports reference wrappers. When a reference
274+
//! wrapper is passed to it, the resulting `hana::optional` will hold a
275+
//! reference to the object instead of the object itself.
276+
//!
272277
//!
273278
//! Example
274279
//! -------

include/boost/hana/optional.hpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0.
1515
#include <boost/hana/bool.hpp>
1616
#include <boost/hana/config.hpp>
1717
#include <boost/hana/core/tag_of.hpp>
18+
#include <boost/hana/detail/as_container_element.hpp>
1819
#include <boost/hana/detail/operators/adl.hpp>
1920
#include <boost/hana/detail/operators/comparable.hpp>
2021
#include <boost/hana/detail/operators/monad.hpp>
@@ -59,6 +60,9 @@ BOOST_HANA_NAMESPACE_BEGIN
5960
constexpr optional(optional const&) = default;
6061
constexpr optional(optional&&) = default;
6162

63+
template <typename U = T, typename = typename std::enable_if<
64+
!std::is_reference<U>::value
65+
>::type>
6266
constexpr optional(T const& t)
6367
: value_(t)
6468
{ }
@@ -72,8 +76,15 @@ BOOST_HANA_NAMESPACE_BEGIN
7276
constexpr optional& operator=(optional&&) = default;
7377

7478
// 5.3.5, Observers
75-
constexpr T const* operator->() const { return &value_; }
76-
constexpr T* operator->() { return &value_; }
79+
template <typename U = T, typename = typename std::enable_if<
80+
!std::is_reference<U>::value
81+
>::type>
82+
constexpr U const* operator->() const { return &value_; }
83+
84+
template <typename U = T, typename = typename std::enable_if<
85+
!std::is_reference<U>::value
86+
>::type>
87+
constexpr U* operator->() { return &value_; }
7788

7889
constexpr T& value() & { return value_; }
7990
constexpr T const& value() const& { return value_; }
@@ -115,7 +126,7 @@ BOOST_HANA_NAMESPACE_BEGIN
115126

116127
template <typename T>
117128
constexpr auto make_just_t::operator()(T&& t) const {
118-
return optional<typename std::decay<T>::type>(
129+
return optional<detail::as_container_element_t<T>>(
119130
static_cast<T&&>(t)
120131
);
121132
}

test/optional/make.ref.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
@copyright Louis Dionne 2015
3+
Distributed under the Boost Software License, Version 1.0.
4+
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
5+
*/
6+
7+
#include <boost/hana/assert.hpp>
8+
#include <boost/hana/optional.hpp>
9+
10+
#include <functional>
11+
namespace hana = boost::hana;
12+
13+
14+
int main() {
15+
{
16+
int i = 0;
17+
auto ref = hana::just(std::ref(i));
18+
19+
int& i_ref = *ref;
20+
BOOST_HANA_RUNTIME_CHECK(&i_ref == &i);
21+
22+
i_ref = 3;
23+
BOOST_HANA_RUNTIME_CHECK(i == 3);
24+
}
25+
26+
{
27+
int const i = 4;
28+
auto ref = hana::just(std::cref(i));
29+
30+
int const& i_ref = *ref;
31+
BOOST_HANA_RUNTIME_CHECK(&i_ref == &i);
32+
BOOST_HANA_RUNTIME_CHECK(i == 4);
33+
}
34+
35+
// Instantiate .value_or to make sure it works with references.
36+
{
37+
int i = 0;
38+
auto ref = hana::just(std::ref(i));
39+
BOOST_HANA_RUNTIME_CHECK(ref.value_or(999) == i);
40+
BOOST_HANA_RUNTIME_CHECK(static_cast<decltype(ref)const&>(ref).value_or(999) == i);
41+
BOOST_HANA_RUNTIME_CHECK(hana::just(std::ref(i)).value_or(999) == i);
42+
}
43+
}

0 commit comments

Comments
 (0)