Skip to content

Commit 9fc8598

Browse files
committed
[bugfix] Fix incorrect result for first and second in nested pair cases
1 parent f36385d commit 9fc8598

File tree

2 files changed

+81
-6
lines changed

2 files changed

+81
-6
lines changed

include/boost/hana/pair.hpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,46 @@ BOOST_HANA_NAMESPACE_BEGIN
161161

162162
template <>
163163
struct first_impl<pair_tag> {
164-
template <typename P>
165-
static constexpr decltype(auto) apply(P&& p)
166-
{ return detail::ebo_get<detail::pix<0>>(static_cast<P&&>(p)); }
164+
template <typename First, typename Second>
165+
static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
166+
return detail::ebo_get<detail::pix<0>>(
167+
static_cast<detail::ebo<detail::pix<0>, First>&>(p)
168+
);
169+
}
170+
template <typename First, typename Second>
171+
static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
172+
return detail::ebo_get<detail::pix<0>>(
173+
static_cast<detail::ebo<detail::pix<0>, First> const&>(p)
174+
);
175+
}
176+
template <typename First, typename Second>
177+
static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
178+
return detail::ebo_get<detail::pix<0>>(
179+
static_cast<detail::ebo<detail::pix<0>, First>&&>(p)
180+
);
181+
}
167182
};
168183

169184
template <>
170185
struct second_impl<pair_tag> {
171-
template <typename P>
172-
static constexpr decltype(auto) apply(P&& p)
173-
{ return detail::ebo_get<detail::pix<1>>(static_cast<P&&>(p)); }
186+
template <typename First, typename Second>
187+
static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
188+
return detail::ebo_get<detail::pix<1>>(
189+
static_cast<detail::ebo<detail::pix<1>, Second>&>(p)
190+
);
191+
}
192+
template <typename First, typename Second>
193+
static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
194+
return detail::ebo_get<detail::pix<1>>(
195+
static_cast<detail::ebo<detail::pix<1>, Second> const&>(p)
196+
);
197+
}
198+
template <typename First, typename Second>
199+
static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
200+
return detail::ebo_get<detail::pix<1>>(
201+
static_cast<detail::ebo<detail::pix<1>, Second>&&>(p)
202+
);
203+
}
174204
};
175205
BOOST_HANA_NAMESPACE_END
176206

test/issues/github_331.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright Louis Dionne 2013-2017
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4+
5+
#include <boost/hana/at.hpp>
6+
#include <boost/hana/first.hpp>
7+
#include <boost/hana/integral_constant.hpp>
8+
#include <boost/hana/pair.hpp>
9+
#include <boost/hana/second.hpp>
10+
#include <boost/hana/tuple.hpp>
11+
12+
#include <type_traits>
13+
namespace hana = boost::hana;
14+
15+
16+
// In GitHub issue #331, we noticed that `first` and `second` could sometimes
17+
// return the wrong member in case of nested pairs. This is due to the way we
18+
// inherit from base classes to enable EBO. We also check for `basic_tuple`,
19+
// because both are implemented similarly.
20+
21+
int main() {
22+
{
23+
using Nested = hana::pair<hana::int_<1>, hana::int_<2>>;
24+
using Pair = hana::pair<hana::int_<0>, Nested>;
25+
Pair pair{};
26+
27+
auto a = hana::first(pair);
28+
static_assert(std::is_same<decltype(a), hana::int_<0>>{}, "");
29+
30+
auto b = hana::second(pair);
31+
static_assert(std::is_same<decltype(b), Nested>{}, "");
32+
}
33+
34+
{
35+
using Nested = hana::basic_tuple<hana::int_<1>, hana::int_<2>>;
36+
using Tuple = hana::basic_tuple<hana::int_<0>, Nested>;
37+
Tuple tuple{};
38+
39+
auto a = hana::at_c<0>(tuple);
40+
static_assert(std::is_same<decltype(a), hana::int_<0>>{}, "");
41+
42+
auto b = hana::at_c<1>(tuple);
43+
static_assert(std::is_same<decltype(b), Nested>{}, "");
44+
}
45+
}

0 commit comments

Comments
 (0)