From ea309d5f79d5eb128a1ce7bcb95054bf0aafb31e Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 13 Sep 2015 12:15:12 -0400 Subject: [PATCH 1/7] [detail] Add detail::as_container_element to support reference_wrappers --- .../hana/detail/as_container_element.hpp | 74 +++++++++++++++++++ test/CMakeLists.txt | 4 +- .../detail/as_container_element/boost_ref.cpp | 32 ++++++++ test/detail/as_container_element/normal.cpp | 23 ++++++ test/detail/as_container_element/std_ref.cpp | 31 ++++++++ 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 include/boost/hana/detail/as_container_element.hpp create mode 100644 test/detail/as_container_element/boost_ref.cpp create mode 100644 test/detail/as_container_element/normal.cpp create mode 100644 test/detail/as_container_element/std_ref.cpp diff --git a/include/boost/hana/detail/as_container_element.hpp b/include/boost/hana/detail/as_container_element.hpp new file mode 100644 index 0000000000..0ee8a30e08 --- /dev/null +++ b/include/boost/hana/detail/as_container_element.hpp @@ -0,0 +1,74 @@ +/*! +@file +Defines `boost::hana::detail::as_container_element_t`. + +@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) + */ + +#ifndef BOOST_HANA_DETAIL_AS_CONTAINER_ELEMENT_HPP +#define BOOST_HANA_DETAIL_AS_CONTAINER_ELEMENT_HPP + +#include +#include + + +// We forward declare `std::reference_wrapper` because including the whole +// `` header is too expensive in terms of compile-time. +// Technically, this is disallowed by the standard, and we'll have to handle +// each standard library separately. See this issue for more information: +// https://github.com/ldionne/hana/issues/176. +// +// Dear Standard Committee, it is about time we get fine grained headers... +#if defined(BOOST_HANA_CONFIG_LIBCPP) + + _LIBCPP_BEGIN_NAMESPACE_STD + template + class _LIBCPP_TYPE_VIS_ONLY reference_wrapper; + _LIBCPP_END_NAMESPACE_STD + +#elif defined(BOOST_HANA_CONFIG_LIBSTDCXX) + + namespace std _GLIBCXX_VISIBILITY(default) { + _GLIBCXX_BEGIN_NAMESPACE_VERSION + template + class reference_wrapper; + _GLIBCXX_END_NAMESPACE_VERSION + } + +#else + +# error "Hana must be taught how to forward declare std::reference_wrapper for your standard library" + +#endif + + +// We also forward declare boost::reference_wrapper, because it's nice to +// interoperate with it too. +namespace boost { template class reference_wrapper; } + + +namespace boost { namespace hana { namespace detail { + template + struct as_container_element_impl { + using type = T; + }; + + template + struct as_container_element_impl> { + using type = T&; + }; + + template + struct as_container_element_impl> { + using type = T&; + }; + + template + using as_container_element_t = typename as_container_element_impl< + typename detail::decay::type + >::type; +}}} // end namespace boost::hana::detail + +#endif // !BOOST_HANA_DETAIL_AS_CONTAINER_ELEMENT_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b35913c7cd..e9b2435425 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,8 +34,10 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/_support) ############################################################################## if (NOT Boost_FOUND) list(APPEND EXCLUDED_UNIT_TESTS + "detail/as_container_element/boost_ref.cpp" + "experimental/printable/*.cpp" "ext/boost/*.cpp" - "experimental/printable/*.cpp") + ) list(APPEND EXCLUDED_PUBLIC_HEADERS "${Boost.Hana_SOURCE_DIR}/include/boost/hana/ext/boost/*.hpp" diff --git a/test/detail/as_container_element/boost_ref.cpp b/test/detail/as_container_element/boost_ref.cpp new file mode 100644 index 0000000000..0acd7af7c7 --- /dev/null +++ b/test/detail/as_container_element/boost_ref.cpp @@ -0,0 +1,32 @@ +/* +@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 + +#include + +#include +namespace hana = boost::hana; +using hana::detail::as_container_element_t; + + +struct T { }; + +static_assert(std::is_same>>{}, ""); +static_assert(std::is_same const>>{}, ""); +static_assert(std::is_same&>>{}, ""); +static_assert(std::is_same const&>>{}, ""); +static_assert(std::is_same&&>>{}, ""); +static_assert(std::is_same const&&>>{}, ""); + +static_assert(std::is_same>>{}, ""); +static_assert(std::is_same const>>{}, ""); +static_assert(std::is_same&>>{}, ""); +static_assert(std::is_same const&>>{}, ""); +static_assert(std::is_same&&>>{}, ""); +static_assert(std::is_same const&&>>{}, ""); + +int main() { } diff --git a/test/detail/as_container_element/normal.cpp b/test/detail/as_container_element/normal.cpp new file mode 100644 index 0000000000..eb64fddfcd --- /dev/null +++ b/test/detail/as_container_element/normal.cpp @@ -0,0 +1,23 @@ +/* +@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 + +#include +namespace hana = boost::hana; +using hana::detail::as_container_element_t; + + +struct T { }; + +static_assert(std::is_same>{}, ""); +static_assert(std::is_same>{}, ""); +static_assert(std::is_same>{}, ""); +static_assert(std::is_same>{}, ""); +static_assert(std::is_same>{}, ""); +static_assert(std::is_same>{}, ""); + +int main() { } diff --git a/test/detail/as_container_element/std_ref.cpp b/test/detail/as_container_element/std_ref.cpp new file mode 100644 index 0000000000..eb8c25725f --- /dev/null +++ b/test/detail/as_container_element/std_ref.cpp @@ -0,0 +1,31 @@ +/* +@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 + +#include +#include +namespace hana = boost::hana; +using hana::detail::as_container_element_t; + + +struct T { }; + +static_assert(std::is_same>>{}, ""); +static_assert(std::is_same const>>{}, ""); +static_assert(std::is_same&>>{}, ""); +static_assert(std::is_same const&>>{}, ""); +static_assert(std::is_same&&>>{}, ""); +static_assert(std::is_same const&&>>{}, ""); + +static_assert(std::is_same>>{}, ""); +static_assert(std::is_same const>>{}, ""); +static_assert(std::is_same&>>{}, ""); +static_assert(std::is_same const&>>{}, ""); +static_assert(std::is_same&&>>{}, ""); +static_assert(std::is_same const&&>>{}, ""); + +int main() { } From f5348c9be292c58143ab9985a64fe93fed182604 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 30 Sep 2015 18:12:33 -0400 Subject: [PATCH 2/7] [tuple] Support reference_wrappers in make_tuple --- include/boost/hana/fwd/tuple.hpp | 7 +++++-- include/boost/hana/tuple.hpp | 6 +++--- test/tuple/make.ref.cpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 test/tuple/make.ref.cpp diff --git a/include/boost/hana/fwd/tuple.hpp b/include/boost/hana/fwd/tuple.hpp index 1624b3d296..8747472b08 100644 --- a/include/boost/hana/fwd/tuple.hpp +++ b/include/boost/hana/fwd/tuple.hpp @@ -159,8 +159,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! //! Given zero or more objects `xs...`, `make` returns a new tuple //! containing those objects. The elements are held by value inside the - //! resulting tuple, and they are hence copied or moved in. This is - //! analogous to `std::make_tuple` for creating Hana tuples. + //! resulting tuple, and they are hence copied or moved in. However, + //! `make` supports reference wrappers. When a reference wrapper + //! is passed to it, the resulting `hana::tuple` will hold a reference + //! to the object enclosed in the reference wrapper instead of the object + //! itself. //! //! //! Example diff --git a/include/boost/hana/tuple.hpp b/include/boost/hana/tuple.hpp index 388d4576b2..6721b83326 100644 --- a/include/boost/hana/tuple.hpp +++ b/include/boost/hana/tuple.hpp @@ -15,7 +15,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include -#include +#include #include #include #include @@ -277,8 +277,8 @@ BOOST_HANA_NAMESPACE_BEGIN template <> struct make_impl { template - static constexpr - tuple::type...> apply(Xs&& ...xs) + static constexpr tuple...> + apply(Xs&& ...xs) { return {static_cast(xs)...}; } }; diff --git a/test/tuple/make.ref.cpp b/test/tuple/make.ref.cpp new file mode 100644 index 0000000000..160df0bf21 --- /dev/null +++ b/test/tuple/make.ref.cpp @@ -0,0 +1,29 @@ +/* +@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 +#include +#include + +#include +namespace hana = boost::hana; + + +int main() { + int i = 0; + char c = 'x'; + hana::tuple refs = hana::make_tuple(std::ref(i), std::cref(c)); + + int& i_ref = hana::at_c<0>(refs); + BOOST_HANA_RUNTIME_CHECK(&i_ref == &i); + + i_ref = 3; + BOOST_HANA_RUNTIME_CHECK(i == 3); + + char const& c_ref = hana::at_c<1>(refs); + BOOST_HANA_RUNTIME_CHECK(&c_ref == &c); + BOOST_HANA_RUNTIME_CHECK(c == 'x'); +} From ec3aff957660d6ef296ed9bc4d5a51d1774ba76d Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 13 Sep 2015 12:15:54 -0400 Subject: [PATCH 3/7] [pair] Support reference_wrappers in make_pair --- include/boost/hana/fwd/pair.hpp | 7 +++++++ include/boost/hana/pair.hpp | 6 +++--- test/pair/make.ref.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/pair/make.ref.cpp diff --git a/include/boost/hana/fwd/pair.hpp b/include/boost/hana/fwd/pair.hpp index 0a36da1875..77f5f330ba 100644 --- a/include/boost/hana/fwd/pair.hpp +++ b/include/boost/hana/fwd/pair.hpp @@ -130,6 +130,13 @@ BOOST_HANA_NAMESPACE_BEGIN //! @relates hana::pair //! //! + //! @note + //! `make` supports reference wrappers. When a reference wrapper + //! is passed to it, the resulting `hana::pair` will hold a reference + //! to the object enclosed in the reference wrapper instead of the object + //! itself. + //! + //! //! Example //! ------- //! @include example/pair/make.cpp diff --git a/include/boost/hana/pair.hpp b/include/boost/hana/pair.hpp index 5a4bf87e23..edfb8bbcc3 100644 --- a/include/boost/hana/pair.hpp +++ b/include/boost/hana/pair.hpp @@ -14,7 +14,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include -#include +#include #include #include #include @@ -122,8 +122,8 @@ BOOST_HANA_NAMESPACE_BEGIN struct make_impl { template static constexpr pair< - typename detail::decay::type, - typename detail::decay::type + detail::as_container_element_t, + detail::as_container_element_t > apply(F&& f, S&& s) { return {static_cast(f), static_cast(s)}; } diff --git a/test/pair/make.ref.cpp b/test/pair/make.ref.cpp new file mode 100644 index 0000000000..d0d04eefda --- /dev/null +++ b/test/pair/make.ref.cpp @@ -0,0 +1,30 @@ +/* +@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 +#include +#include +#include + +#include +namespace hana = boost::hana; + + +int main() { + int i = 0; + char c = 'x'; + hana::pair refs = hana::make_pair(std::ref(i), std::cref(c)); + + int& i_ref = hana::first(refs); + BOOST_HANA_RUNTIME_CHECK(&i_ref == &i); + + i_ref = 3; + BOOST_HANA_RUNTIME_CHECK(i == 3); + + char const& c_ref = hana::second(refs); + BOOST_HANA_RUNTIME_CHECK(&c_ref == &c); + BOOST_HANA_RUNTIME_CHECK(c == 'x'); +} From e2f764f2f710cc6e023c43ef8e4b2f5766ddea59 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 13 Sep 2015 12:20:33 -0400 Subject: [PATCH 4/7] [optional] Add support for reference_wrapper in just() --- include/boost/hana/fwd/optional.hpp | 5 ++++ include/boost/hana/optional.hpp | 17 ++++++++++-- test/optional/make.ref.cpp | 43 +++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 test/optional/make.ref.cpp diff --git a/include/boost/hana/fwd/optional.hpp b/include/boost/hana/fwd/optional.hpp index 9763040418..c7e7e12cea 100644 --- a/include/boost/hana/fwd/optional.hpp +++ b/include/boost/hana/fwd/optional.hpp @@ -297,6 +297,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! `make(x)` is equivalent to `just(x)`. This is provided //! for consistency with the other `make<...>` functions. //! + //! @note + //! `make` 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 //! ------- diff --git a/include/boost/hana/optional.hpp b/include/boost/hana/optional.hpp index 7316115616..3babd7a46a 100644 --- a/include/boost/hana/optional.hpp +++ b/include/boost/hana/optional.hpp @@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include #include #include @@ -59,6 +60,9 @@ BOOST_HANA_NAMESPACE_BEGIN constexpr optional(optional const&) = default; constexpr optional(optional&&) = default; + template ::value + >::type> constexpr optional(T const& t) : value_(t) { } @@ -72,8 +76,15 @@ BOOST_HANA_NAMESPACE_BEGIN constexpr optional& operator=(optional&&) = default; // 5.3.5, Observers - constexpr T const* operator->() const { return &value_; } - constexpr T* operator->() { return &value_; } + template ::value + >::type> + constexpr U const* operator->() const { return &value_; } + + template ::value + >::type> + constexpr U* operator->() { return &value_; } constexpr T& value() & { return value_; } constexpr T const& value() const& { return value_; } @@ -115,7 +126,7 @@ BOOST_HANA_NAMESPACE_BEGIN template constexpr auto make_just_t::operator()(T&& t) const { - return optional::type>( + return optional>( static_cast(t) ); } diff --git a/test/optional/make.ref.cpp b/test/optional/make.ref.cpp new file mode 100644 index 0000000000..099f256605 --- /dev/null +++ b/test/optional/make.ref.cpp @@ -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 +#include + +#include +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(ref).value_or(999) == i); + BOOST_HANA_RUNTIME_CHECK(hana::just(std::ref(i)).value_or(999) == i); + } +} From 0fad2b915f47a916d821ad55091c0deaa88ab5a6 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 13 Sep 2015 13:01:51 -0400 Subject: [PATCH 5/7] [lazy] Add support for reference_wrapper in make_lazy --- include/boost/hana/fwd/lazy.hpp | 4 +++ include/boost/hana/lazy.hpp | 8 ++--- test/lazy/make.ref.cpp | 59 +++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 test/lazy/make.ref.cpp diff --git a/include/boost/hana/fwd/lazy.hpp b/include/boost/hana/fwd/lazy.hpp index c5f96e87b1..ff1f5118ae 100644 --- a/include/boost/hana/fwd/lazy.hpp +++ b/include/boost/hana/fwd/lazy.hpp @@ -92,6 +92,10 @@ BOOST_HANA_NAMESPACE_BEGIN //! equal to `x`, and `make(f)(x1, ..., xN)` is a lazy function //! call that is equal to `f(x1, ..., xN)` when it is `eval`uated. //! + //! `make` 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(f)(x1, ..., xN)` is //! equivalent to diff --git a/include/boost/hana/lazy.hpp b/include/boost/hana/lazy.hpp index 073fbca5af..c3dfc67d24 100644 --- a/include/boost/hana/lazy.hpp +++ b/include/boost/hana/lazy.hpp @@ -15,7 +15,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include -#include +#include #include #include #include @@ -71,7 +71,7 @@ BOOST_HANA_NAMESPACE_BEGIN template constexpr lazy_apply_t< std::make_index_sequence, - X, typename detail::decay::type... + X, detail::as_container_element_t... > operator()(Args&& ...args) const& { return {detail::lazy_secret{}, hana::get_impl<0>(storage_), static_cast(args)...}; @@ -80,7 +80,7 @@ BOOST_HANA_NAMESPACE_BEGIN template constexpr lazy_apply_t< std::make_index_sequence, - X, typename detail::decay::type... + X, detail::as_container_element_t... > operator()(Args&& ...args) && { return {detail::lazy_secret{}, static_cast(hana::get_impl<0>(storage_)), @@ -95,7 +95,7 @@ BOOST_HANA_NAMESPACE_BEGIN template <> struct make_impl { template - static constexpr lazy_value_t::type> apply(X&& x) { + static constexpr lazy_value_t> apply(X&& x) { return {detail::lazy_secret{}, static_cast(x)}; } }; diff --git a/test/lazy/make.ref.cpp b/test/lazy/make.ref.cpp new file mode 100644 index 0000000000..22ed24853d --- /dev/null +++ b/test/lazy/make.ref.cpp @@ -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 +#include +#include + +#include +namespace hana = boost::hana; + + +// We make it non-copyable and non-movable to make sure it is taken by +// reference below. +template +struct Function; + +template +struct Function { + std::function f_; + + Function(std::function f) : f_(f) { } + Function(Function const&) = delete; + Function(Function &&) = delete; + + template + decltype(auto) operator()(T&& ...t) const { + return f_(static_cast(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 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'); + } +} From df657441e1486aa8a0f83039363aae0f03795011 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sun, 13 Sep 2015 16:02:25 -0400 Subject: [PATCH 6/7] [tutorial] Document that some containers can hold references --- doc/tutorial.hpp | 37 +++++++++++++++++++++++++-------- example/tutorial/containers.cpp | 28 ++++++++++++++++++------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/doc/tutorial.hpp b/doc/tutorial.hpp index e546768bce..dfe98051f6 100644 --- a/doc/tutorial.hpp +++ b/doc/tutorial.hpp @@ -2034,21 +2034,40 @@ and so on. @subsection tutorial-containers-elements Container elements -In Hana, containers own their elements. When a container is created, it makes -a _copy_ of the elements used to initialize it and stores them inside the -container. Of course, unnecessary copies are avoided by using move semantics. -Because of those owning semantics, the lifetime of the objects inside the -container is the same as that of the container. +In Hana, containers own their elements. When a container is created, it +normally makes a _copy_ of the elements used to initialize it and stores them +inside the container. Of course, unnecessary copies are avoided by using move +semantics. Because of those owning semantics, the lifetime of the objects +inside the container is the same as that of the container. @snippet example/tutorial/containers.cpp lifetime -Much like containers in the standard library, containers in Hana expect their -elements to be objects. For this reason, references _may not_ be stored in -them. When references must be stored inside a container, one should use a -`std::reference_wrapper` instead: +However, some containers allow storing references instead of actual objects. +In that case, the owning semantics explained above do not hold anymore. For +example, it is possible to create a `hana::tuple` holding references as +follows: + +@snippet example/tutorial/containers.cpp reference_tuple + +@note +Of course, a single tuple can also hold some elements by value and other +elements by reference. + +Since explicitly specifying the type of the container to achieve by-reference +semantics can be cumbersome (and sometimes downright impossible when that +type is implementation-defined), the `make_xxx` family of functions also +support the use of `reference_wrapper`s: @snippet example/tutorial/containers.cpp reference_wrapper +When passed to a `hana::make_xxx` function, `std::reference_wrapper`s and +`boost::reference_wrapper`s will cause the container to hold a reference +instead of a `reference_wrapper`. Of course, only the `make_xxx` functions +associated to containers that support holding references implement this +special behavior. To know whether a container is able to hold references +(and implements this behavior), one should consult the reference documentation +for that container. + diff --git a/example/tutorial/containers.cpp b/example/tutorial/containers.cpp index f98f755d9c..7083093dfa 100644 --- a/example/tutorial/containers.cpp +++ b/example/tutorial/containers.cpp @@ -73,17 +73,29 @@ std::string& s = xs[0_c]; }{ +//! [reference_tuple] +std::string hello = "Hello"; +std::vector world = {'W', 'o', 'r', 'l', 'd'}; + +hana::tuple&> xs{hello, world}; + +// s is a reference to `hello` +std::string& s = xs[0_c]; +BOOST_HANA_RUNTIME_CHECK(&s == &hello); +//! [reference_tuple] + +}{ + //! [reference_wrapper] -std::vector ints = { /* huge vector of ints */ }; -std::vector strings = { /* huge vector of strings */ }; +std::string hello = "Hello"; +std::vector world = {'W', 'o', 'r', 'l', 'd'}; -auto map = hana::make_map( - hana::make_pair(hana::type_c, std::ref(ints)), - hana::make_pair(hana::type_c, std::ref(strings)) -); +auto xs = hana::make_tuple(std::ref(hello), std::ref(world)); -auto& v = map[hana::type_c].get(); -BOOST_HANA_RUNTIME_CHECK(&v == &ints); +std::string& hello_ref = xs[0_c]; +std::vector& world_ref = xs[1_c]; +BOOST_HANA_RUNTIME_CHECK(&hello_ref == &hello); +BOOST_HANA_RUNTIME_CHECK(&world_ref == &world); //! [reference_wrapper] } From 5e45f3d0ff50a3f5ca29c433ba2b59c74c1a44fe Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 14 Dec 2015 13:29:26 -0500 Subject: [PATCH 7/7] Teach Hana how to forward declare reference_wrapper on Windows --- include/boost/hana/detail/as_container_element.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/hana/detail/as_container_element.hpp b/include/boost/hana/detail/as_container_element.hpp index 0ee8a30e08..e493414112 100644 --- a/include/boost/hana/detail/as_container_element.hpp +++ b/include/boost/hana/detail/as_container_element.hpp @@ -37,6 +37,13 @@ Distributed under the Boost Software License, Version 1.0. _GLIBCXX_END_NAMESPACE_VERSION } +#elif defined(BOOST_HANA_CONFIG_LIBMSVCCXX) + + namespace std { + template + class reference_wrapper; + } + #else # error "Hana must be taught how to forward declare std::reference_wrapper for your standard library"