Skip to content

Commit 3fe5ee4

Browse files
committed
[optional] Add support for reference_wrapper in just()
1 parent f48b10c commit 3fe5ee4

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
@@ -250,6 +250,11 @@ namespace boost { namespace hana {
250250
//! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
251251
//! for consistency with the other `make<...>` functions.
252252
//!
253+
//! @note
254+
//! `make<optional_tag>` supports reference wrappers. When a reference
255+
//! wrapper is passed to it, the resulting `hana::optional` will hold a
256+
//! reference to the object instead of the object itself.
257+
//!
253258
//!
254259
//! Example
255260
//! -------

include/boost/hana/optional.hpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Distributed under the Boost Software License, Version 1.0.
1414

1515
#include <boost/hana/bool.hpp>
1616
#include <boost/hana/core/tag_of.hpp>
17+
#include <boost/hana/detail/as_container_element.hpp>
1718
#include <boost/hana/detail/operators/adl.hpp>
1819
#include <boost/hana/detail/operators/comparable.hpp>
1920
#include <boost/hana/detail/operators/monad.hpp>
@@ -58,6 +59,9 @@ namespace boost { namespace hana {
5859
constexpr optional(optional const&) = default;
5960
constexpr optional(optional&&) = default;
6061

62+
template <typename U = T, typename = typename std::enable_if<
63+
!std::is_reference<U>::value
64+
>::type>
6165
constexpr optional(T const& t)
6266
: value_(t)
6367
{ }
@@ -71,8 +75,15 @@ namespace boost { namespace hana {
7175
constexpr optional& operator=(optional&&) = default;
7276

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

7788
constexpr T& value() & { return value_; }
7889
constexpr T const& value() const& { return value_; }
@@ -114,7 +125,7 @@ namespace boost { namespace hana {
114125

115126
template <typename T>
116127
constexpr auto make_just_t::operator()(T&& t) const {
117-
return optional<typename std::decay<T>::type>(
128+
return optional<detail::as_container_element_t<T>>(
118129
static_cast<T&&>(t)
119130
);
120131
}

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)