Skip to content

Commit

Permalink
[optional] Add support for reference_wrapper in just()
Browse files Browse the repository at this point in the history
  • Loading branch information
ldionne committed Nov 15, 2015
1 parent 03b3d94 commit 61f9074
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
5 changes: 5 additions & 0 deletions include/boost/hana/fwd/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ namespace boost { namespace hana {
//! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
//! for consistency with the other `make<...>` functions.
//!
//! @note
//! `make<optional_tag>` supports reference wrappers. When a reference
//! wrapper is passed to it, the resulting `hana::optional` will hold a
//! reference to the object instead of the object itself.
//!
//!
//! Example
//! -------
Expand Down
17 changes: 14 additions & 3 deletions include/boost/hana/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Distributed under the Boost Software License, Version 1.0.

#include <boost/hana/bool.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/as_container_element.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
#include <boost/hana/detail/operators/monad.hpp>
Expand Down Expand Up @@ -58,6 +59,9 @@ namespace boost { namespace hana {
constexpr optional(optional const&) = default;
constexpr optional(optional&&) = default;

template <typename U = T, typename = typename std::enable_if<
!std::is_reference<U>::value
>::type>
constexpr optional(T const& t)
: value_(t)
{ }
Expand All @@ -71,8 +75,15 @@ namespace boost { namespace hana {
constexpr optional& operator=(optional&&) = default;

// 5.3.5, Observers
constexpr T const* operator->() const { return &value_; }
constexpr T* operator->() { return &value_; }
template <typename U = T, typename = typename std::enable_if<
!std::is_reference<U>::value
>::type>
constexpr U const* operator->() const { return &value_; }

template <typename U = T, typename = typename std::enable_if<
!std::is_reference<U>::value
>::type>
constexpr U* operator->() { return &value_; }

constexpr T& value() & { return value_; }
constexpr T const& value() const& { return value_; }
Expand Down Expand Up @@ -114,7 +125,7 @@ namespace boost { namespace hana {

template <typename T>
constexpr auto make_just_t::operator()(T&& t) const {
return optional<typename std::decay<T>::type>(
return optional<detail::as_container_element_t<T>>(
static_cast<T&&>(t)
);
}
Expand Down
43 changes: 43 additions & 0 deletions test/optional/make.ref.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/

#include <boost/hana/assert.hpp>
#include <boost/hana/optional.hpp>

#include <functional>
namespace hana = boost::hana;


int main() {
{
int i = 0;
auto ref = hana::just(std::ref(i));

int& i_ref = *ref;
BOOST_HANA_RUNTIME_CHECK(&i_ref == &i);

i_ref = 3;
BOOST_HANA_RUNTIME_CHECK(i == 3);
}

{
int const i = 4;
auto ref = hana::just(std::cref(i));

int const& i_ref = *ref;
BOOST_HANA_RUNTIME_CHECK(&i_ref == &i);
BOOST_HANA_RUNTIME_CHECK(i == 4);
}

// Instantiate .value_or to make sure it works with references.
{
int i = 0;
auto ref = hana::just(std::ref(i));
BOOST_HANA_RUNTIME_CHECK(ref.value_or(999) == i);
BOOST_HANA_RUNTIME_CHECK(static_cast<decltype(ref)const&>(ref).value_or(999) == i);
BOOST_HANA_RUNTIME_CHECK(hana::just(std::ref(i)).value_or(999) == i);
}
}

0 comments on commit 61f9074

Please sign in to comment.