Skip to content

Commit

Permalink
[lazy] Add support for reference_wrapper in make_lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
ldionne committed Nov 15, 2015
1 parent 61f9074 commit b1ae885
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 4 deletions.
4 changes: 4 additions & 0 deletions include/boost/hana/fwd/lazy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ namespace boost { namespace hana {
//! equal to `x`, and `make<lazy_tag>(f)(x1, ..., xN)` is a lazy function
//! call that is equal to `f(x1, ..., xN)` when it is `eval`uated.
//!
//! `make<lazy_tag>` supports reference wrappers. When a reference wrapper
//! is passed to it, the resulting `hana::lazy` will hold a reference
//! to the object instead of the object itself.
//!
//! @note
//! It is interesting to note that `make<lazy_tag>(f)(x1, ..., xN)` is
//! equivalent to
Expand Down
8 changes: 4 additions & 4 deletions include/boost/hana/lazy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Distributed under the Boost Software License, Version 1.0.

#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/detail/as_container_element.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/monad.hpp>
#include <boost/hana/functional/apply.hpp>
Expand Down Expand Up @@ -70,7 +70,7 @@ namespace boost { namespace hana {
template <typename ...Args>
constexpr lazy_apply_t<
std::make_index_sequence<sizeof...(Args)>,
X, typename detail::decay<Args>::type...
X, detail::as_container_element_t<Args>...
> operator()(Args&& ...args) const& {
return {detail::lazy_secret{},
hana::get_impl<0>(storage_), static_cast<Args&&>(args)...};
Expand All @@ -79,7 +79,7 @@ namespace boost { namespace hana {
template <typename ...Args>
constexpr lazy_apply_t<
std::make_index_sequence<sizeof...(Args)>,
X, typename detail::decay<Args>::type...
X, detail::as_container_element_t<Args>...
> operator()(Args&& ...args) && {
return {detail::lazy_secret{},
static_cast<X&&>(hana::get_impl<0>(storage_)),
Expand All @@ -94,7 +94,7 @@ namespace boost { namespace hana {
template <>
struct make_impl<lazy_tag> {
template <typename X>
static constexpr lazy_value_t<typename detail::decay<X>::type> apply(X&& x) {
static constexpr lazy_value_t<detail::as_container_element_t<X>> apply(X&& x) {
return {detail::lazy_secret{}, static_cast<X&&>(x)};
}
};
Expand Down
59 changes: 59 additions & 0 deletions test/lazy/make.ref.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
@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/eval.hpp>
#include <boost/hana/lazy.hpp>

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


// We make it non-copyable and non-movable to make sure it is taken by
// reference below.
template <typename Signature>
struct Function;

template <typename Return, typename ...Args>
struct Function<Return(Args...)> {
std::function<Return(Args...)> f_;

Function(std::function<Return(Args...)> f) : f_(f) { }
Function(Function const&) = delete;
Function(Function &&) = delete;

template <typename ...T>
decltype(auto) operator()(T&& ...t) const {
return f_(static_cast<T&&>(t)...);
}
};

int main() {
// lazy value
{
int i = 3;
auto lazy = hana::make_lazy(std::ref(i));
int& i_ref = hana::eval(lazy);
BOOST_HANA_RUNTIME_CHECK(&i_ref == &i);
}

// lazy function call
{
Function<void(int&, char&)> f([](int& a, char& b) -> void {
a = 10;
b = 'z';
});
int a = 3;
char b = 'b';
auto lazy = hana::make_lazy(std::ref(f))(std::ref(a), std::ref(b));

BOOST_HANA_RUNTIME_CHECK(a == 3);
BOOST_HANA_RUNTIME_CHECK(b == 'b');
hana::eval(lazy);
BOOST_HANA_RUNTIME_CHECK(a == 10);
BOOST_HANA_RUNTIME_CHECK(b == 'z');
}
}

0 comments on commit b1ae885

Please sign in to comment.