Skip to content

Commit

Permalink
Add set-theoretic operations to hana::map
Browse files Browse the repository at this point in the history
Closes #350 

Big thanks to @shreyans800755 for his great work!
  • Loading branch information
ldionne authored Jun 24, 2017
2 parents 283d749 + a88133a commit 7533611
Show file tree
Hide file tree
Showing 16 changed files with 661 additions and 90 deletions.
46 changes: 46 additions & 0 deletions example/map/difference.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright Louis Dionne 2013-2017
// 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/difference.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/map.hpp>
#include <boost/hana/string.hpp>

#include <string>
namespace hana = boost::hana;
using namespace hana::literals;


constexpr auto m1 = hana::make_map(
hana::make_pair("key1"_s, hana::type_c<std::string>),
hana::make_pair("key2"_s, hana::type_c<std::string>)
);

constexpr auto m2 = hana::make_map(
hana::make_pair("key3"_s, hana::type_c<std::string>),
hana::make_pair("key4"_s, hana::type_c<std::string>),
hana::make_pair("key5"_s, hana::type_c<std::string>)
);

constexpr auto m3 = hana::make_map(
hana::make_pair("key1"_s, hana::type_c<std::string>),
hana::make_pair("key4"_s, hana::type_c<int>),
hana::make_pair("key2"_s, hana::type_c<long long>)
);

int main() {
BOOST_HANA_CONSTANT_CHECK(hana::difference(m1, m2) == m1);

BOOST_HANA_CONSTANT_CHECK(hana::difference(m1, m3) == hana::make_map());

BOOST_HANA_CONSTANT_CHECK(hana::difference(m3, m1) == hana::make_map(
hana::make_pair("key4"_s, hana::type_c<int>)
));

BOOST_HANA_CONSTANT_CHECK(hana::difference(m2, m3) == hana::make_map(
hana::make_pair("key3"_s, hana::type_c<std::string>),
hana::make_pair("key5"_s, hana::type_c<std::string>)
));
}
47 changes: 47 additions & 0 deletions example/map/intersection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Louis Dionne 2013-2017
// 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/equal.hpp>
#include <boost/hana/intersection.hpp>
#include <boost/hana/map.hpp>
#include <boost/hana/string.hpp>

#include <string>
namespace hana = boost::hana;
using namespace hana::literals;


constexpr auto m1 = hana::make_map(
hana::make_pair("key1"_s, hana::type_c<std::string>),
hana::make_pair("key2"_s, hana::type_c<std::string>)
);

constexpr auto m2 = hana::make_map(
hana::make_pair("key3"_s, hana::type_c<std::string>),
hana::make_pair("key4"_s, hana::type_c<std::string>),
hana::make_pair("key5"_s, hana::type_c<std::string>)
);

BOOST_HANA_CONSTANT_CHECK(hana::intersection(m1, m2) == hana::make_map());

constexpr auto m3 = hana::make_map(
hana::make_pair(hana::type_c<int>, hana::int_c<1>),
hana::make_pair(hana::type_c<bool>, hana::bool_c<true>),
hana::make_pair(hana::type_c<std::string>, "hana"_s),
hana::make_pair(hana::type_c<float>, hana::int_c<100>)
);

constexpr auto m4 = hana::make_map(
hana::make_pair(hana::type_c<char>, hana::char_c<'c'>),
hana::make_pair(hana::type_c<bool>, hana::bool_c<false>),
hana::make_pair(hana::type_c<std::string>, "boost"_s)
);

BOOST_HANA_CONSTANT_CHECK(hana::intersection(m3, m4) == hana::make_map(
hana::make_pair(hana::type_c<bool>, hana::bool_c<true>),
hana::make_pair(hana::type_c<std::string>, "hana"_s)
));

int main() { }
33 changes: 33 additions & 0 deletions example/map/symmetric_difference.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright Louis Dionne 2013-2017
// 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/map.hpp>
#include <boost/hana/symmetric_difference.hpp>

namespace hana = boost::hana;


constexpr auto m1 = hana::make_map(
hana::make_pair(hana::type_c<int>, 1),
hana::make_pair(hana::type_c<bool>, hana::true_c)
);

constexpr auto m2 = hana::make_map(
hana::make_pair(hana::type_c<float>, 1.0),
hana::make_pair(hana::type_c<long long>, 2LL),
hana::make_pair(hana::type_c<int>, 3)
);

constexpr auto result_m = hana::make_map(
hana::make_pair(hana::type_c<bool>, hana::true_c),
hana::make_pair(hana::type_c<float>, 1.0),
hana::make_pair(hana::type_c<long long>, 2LL)
);

int main() {
BOOST_HANA_RUNTIME_CHECK(
hana::symmetric_difference(m1, m2) == result_m
);
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/set.hpp>
#include <boost/hana/symmetric_difference.hpp>
#include <boost/hana/type.hpp>

namespace hana = boost::hana;


Expand Down
1 change: 1 addition & 0 deletions include/boost/hana/difference.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/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/erase_key.hpp>


BOOST_HANA_NAMESPACE_BEGIN
Expand Down
40 changes: 4 additions & 36 deletions include/boost/hana/fwd/difference.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,18 @@ Distributed under the Boost Software License, Version 1.0.


BOOST_HANA_NAMESPACE_BEGIN
//! Returns the set-theoretic difference of two sets.
//! @relates hana::set
//!
//! Given two sets `xs` and `ys`, `difference(xs, ys)` is a new set
//! containing all the elements of `xs` that are _not_ contained in `ys`.
//! For any object `x`, the following holds:
//! @code
//! x ^in^ difference(xs, ys) if and only if x ^in^ xs && !(x ^in^ ys)
//! @endcode
//!
//!
//! @note
//! This operation is not commutative, i.e. `difference(xs, ys)` is not
//! necessarily the same as `difference(ys, xs)`. Indeed, consider the
//! case where `xs` is empty and `ys` isn't. Then, `difference(xs, ys)`
//! is empty but `difference(ys, xs)` is equal to `ys`. For the symmetric
//! version of this operation, see `symmetric_difference`.
//!
//!
//! @param xs
//! A set to remove values from.
//!
//! @param ys
//! The set whose values are removed from `xs`.
//!
//!
//! Example
//! -------
//! @include example/difference.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto difference = [](auto&& xs, auto&& ys) {
return tag-dispatched;
};
#else
// Note: This function is documented per datatype/concept only.
//! @cond
template <typename S, typename = void>
struct difference_impl : difference_impl<S, when<true>> { };
//! @endcond

struct difference_t {
template <typename Xs, typename Ys>
constexpr auto operator()(Xs&& xs, Ys&& ys) const;
constexpr auto operator()(Xs&&, Ys&&) const;
};

constexpr difference_t difference{};
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_DIFFERENCE_HPP
29 changes: 4 additions & 25 deletions include/boost/hana/fwd/intersection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,18 @@ Distributed under the Boost Software License, Version 1.0.


BOOST_HANA_NAMESPACE_BEGIN
//! Returns the intersection of two sets.
//! @relates hana::set
//!
//! Given two sets `xs` and `ys`, `intersection(xs, ys)` is a new set
//! containing exactly those elements that are present both in `xs` and
//! in `ys`. In other words, the following holds for any object `x`:
//! @code
//! x ^in^ intersection(xs, ys) if and only if x ^in^ xs && x ^in^ ys
//! @endcode
//!
//!
//! @param xs, ys
//! Two sets to intersect.
//!
//!
//! Example
//! -------
//! @include example/intersection.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto intersection = [](auto&& xs, auto&& ys) {
return tag-dispatched;
};
#else
// Note: This function is documented per datatype/concept only.
//! @cond
template <typename S, typename = void>
struct intersection_impl : intersection_impl<S, when<true>> { };
//! @endcond

struct intersection_t {
template <typename Xs, typename Ys>
constexpr auto operator()(Xs&& xs, Ys&& ys) const;
constexpr auto operator()(Xs&&, Ys&&) const;
};

constexpr intersection_t intersection{};
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_INTERSECTION_HPP
95 changes: 95 additions & 0 deletions include/boost/hana/fwd/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,101 @@ BOOST_HANA_NAMESPACE_BEGIN
return tag-dispatched;
};
#endif

//! Returns the intersection of two maps.
//! @relates hana::map
//!
//! Given two maps `xs` and `ys`, `intersection(xs, ys)` is a new map
//! containing exactly those (key, value) pairs from xs, for which key
//! is present in `ys`.
//! In other words, the following holds for any object `pair(k, v)`:
//! @code
//! pair(k, v) ^in^ intersection(xs, ys) if and only if (k, v) ^in^ xs && k ^in^ keys(ys)
//! @endcode
//!
//!
//! @note
//! This function is not commutative, i.e. `intersection(xs, ys)` is not
//! necessarily the same as `intersection(ys, xs)`. Indeed, the set of keys
//! in `intersection(xs, ys)` is always the same as the set of keys in
//! `intersection(ys, xs)`, but the value associated to each key may be
//! different. `intersection(xs, ys)` contains values present in `xs`, and
//! `intersection(ys, xs)` contains values present in `ys`.
//!
//!
//! @param xs, ys
//! Two maps to intersect.
//!
//!
//! Example
//! -------
//! @include example/map/intersection.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto intersection = [](auto&& xs, auto&& ys) {
return tag-dispatched;
};
#endif

//! Returns the difference of two maps.
//! @relates hana::map
//!
//! Given two maps `xs` and `ys`, `difference(xs, ys)` is a new map
//! containing exactly those (key, value) pairs from xs, for which key
//! is not present in `keys(ys)`.
//! In other words, the following holds for any object `pair(k, v)`:
//! @code
//! pair(k, v) ^in^ difference(xs, ys) if and only if (k, v) ^in^ xs && k ^not in^ keys(ys)
//! @endcode
//!
//!
//! @note
//! This function is not commutative, i.e. `difference(xs, ys)` is not
//! necessarily the same as `difference(ys, xs)`.
//! Indeed, consider the case where `xs` is empty and `ys` isn't.
//! In that case, `difference(xs, ys)` is empty, but `difference(ys, xs)`
//! is equal to `ys`.
//! For symmetric version of this operation, see `symmetric_difference`.
//!
//!
//! @param xs, ys
//! Two maps to compute the difference of.
//!
//!
//! Example
//! -------
//! @include example/map/intersection.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto difference = [](auto&& xs, auto&& ys) {
return tag-dispatched;
};
#endif

//! Returns the symmetric set-theoretic difference of two maps.
//! @relates hana::map
//!
//! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new
//! map containing all the elements of `xs` whose keys are not contained in `keys(ys)`,
//! and all the elements of `ys` whose keys are not contained in `keys(xs)`. The
//! symmetric difference of two maps satisfies the following:
//! @code
//! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs))
//! @endcode
//!
//!
//! @param xs, ys
//! Two maps to compute the symmetric difference of.
//!
//!
//! Example
//! -------
//! @include example/map/symmetric_difference.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) {
return tag-dispatched;
};
#endif


BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_MAP_HPP
Loading

0 comments on commit 7533611

Please sign in to comment.