Skip to content

Commit

Permalink
Close #116 - Add insert support for map
Browse files Browse the repository at this point in the history
Let's dance put on your red shoes and dance the blues!
  • Loading branch information
edouarda committed Jan 11, 2016
1 parent a80bba8 commit 5add9dd
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 12 deletions.
50 changes: 38 additions & 12 deletions brigand/sequences/map.hpp
Expand Up @@ -12,21 +12,50 @@

namespace brigand
{

template <typename M, typename K>
using lookup = decltype(M::at(type_<K>{}));

namespace detail
{
template <class... T>
struct map_impl;

template <class K, class... T>
struct map_inserter_impl
{
using index_type = typename K::first_type;
using map_type = map_impl<T...>;
using find_result = lookup<map_type, index_type>;
using type = decltype(map_type::template insert_impl<K>(find_result{}));
};

template <class... T>
struct map_inserter
{
template <class K, typename U>
static map_impl<T...> insert_impl(U);

template <class K>
static map_impl<T..., K> insert_impl(no_such_type_);

template <class K>
static typename map_inserter_impl<K, T...>::type insert(type_<K>);
};

template <>
struct map_impl<>
{
template <typename U>
static no_such_type_ at(U);

template <class K>
static map_impl<K> insert(type_<K>);
};

// fastlane for constant amortized time
template <class T0>
struct map_impl<T0>
struct map_impl<T0> : map_inserter<T0>
{
static typename T0::second_type at(type_<typename T0::first_type>);

Expand All @@ -35,7 +64,7 @@ namespace detail
};

template <class T0, class T1>
struct map_impl<T0, T1>
struct map_impl<T0, T1> : map_inserter<T0, T1>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -45,7 +74,7 @@ namespace detail
};

template <class T0, class T1, class T2>
struct map_impl<T0, T1, T2>
struct map_impl<T0, T1, T2> : map_inserter<T0, T1, T2>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -56,7 +85,7 @@ namespace detail
};

template <class T0, class T1, class T2, class T3>
struct map_impl<T0, T1, T2, T3>
struct map_impl<T0, T1, T2, T3> : map_inserter<T0, T1, T2, T3>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -68,7 +97,7 @@ namespace detail
};

template <class T0, class T1, class T2, class T3, class T4>
struct map_impl<T0, T1, T2, T3, T4>
struct map_impl<T0, T1, T2, T3, T4> : map_inserter<T0, T1, T2, T3, T4>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -81,7 +110,7 @@ namespace detail
};

template <class T0, class T1, class T2, class T3, class T4, class T5>
struct map_impl<T0, T1, T2, T3, T4, T5>
struct map_impl<T0, T1, T2, T3, T4, T5> : map_inserter<T0, T1, T2, T3, T4, T5>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -95,7 +124,7 @@ namespace detail
};

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6>
struct map_impl<T0, T1, T2, T3, T4, T5, T6>
struct map_impl<T0, T1, T2, T3, T4, T5, T6> : map_inserter<T0, T1, T2, T3, T4, T5, T6>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -110,7 +139,7 @@ namespace detail
};

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
struct map_impl<T0, T1, T2, T3, T4, T5, T6, T7>
struct map_impl<T0, T1, T2, T3, T4, T5, T6, T7> : map_inserter<T0, T1, T2, T3, T4, T5, T6, T7>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -127,7 +156,7 @@ namespace detail


template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class... T>
struct map_impl<T0, T1, T2, T3, T4, T5, T6, T7, T...>
struct map_impl<T0, T1, T2, T3, T4, T5, T6, T7, T...> : map_inserter<T0, T1, T2, T3, T4, T5, T6, T7, T...>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
Expand All @@ -151,7 +180,4 @@ namespace detail
}
template<class... Ts>
using map = typename detail::make_map<Ts...>::type;

template <typename M, typename K>
using lookup = decltype(M::at(type_<K>{}));
}
67 changes: 67 additions & 0 deletions test/map_test.cpp
Expand Up @@ -2,6 +2,7 @@
#include <brigand/sequences/map.hpp>
#include <brigand/sequences/size.hpp>
#include <brigand/sequences/at.hpp>
#include <brigand/sequences/insert.hpp>

static_assert(brigand::detail::has_at_method<brigand::map<>>::value, "at not detected!");

Expand Down Expand Up @@ -49,3 +50,69 @@ static_assert(std::is_same<brigand::at<big_map, type_eight>, type_seven>::value,
static_assert(std::is_same<brigand::at<big_map, type_nine>, type_eight>::value, "not found in big map!");
static_assert(std::is_same<brigand::at<big_map, void>, float****>::value, "not found in big map!");
static_assert(std::is_same<brigand::at<big_map, bool>, brigand::no_such_type_>::value, "found in big map!");

// test insertions all the way up to the fast lanes

using pair_one = brigand::pair<type_one, int>;
using pair_two = brigand::pair<type_two, type_one>;
using pair_three = brigand::pair<type_three, type_two>;
using pair_four = brigand::pair<type_four, type_three>;
using pair_five = brigand::pair<type_five, type_four>;
using pair_six = brigand::pair<type_six, type_five>;
using pair_seven = brigand::pair<type_seven, type_six>;
using pair_eight = brigand::pair<type_eight, type_seven>;
using pair_nine = brigand::pair<type_nine, type_eight>;
using pair_ten = brigand::pair<void, float****>;

using map_of_one = brigand::map<pair_one>;
static_assert(std::is_same<brigand::insert<brigand::map<>, pair_one>, map_of_one>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_one, pair_one>, map_of_one>::value, "insertion failed");

using map_of_two = brigand::map<pair_one, pair_two>;
static_assert(std::is_same<brigand::insert<map_of_one, pair_two>, map_of_two>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_two, pair_two>, map_of_two>::value, "insertion failed");

using map_of_three = brigand::map<pair_one, pair_two, pair_three>;
static_assert(std::is_same<brigand::insert<map_of_two, pair_three>, map_of_three>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_three, pair_three>, map_of_three>::value, "insertion failed");

using map_of_four = brigand::map<pair_one, pair_two, pair_three, pair_four>;
static_assert(std::is_same<brigand::insert<map_of_three, pair_four>, map_of_four>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_four, pair_four>, map_of_four>::value, "insertion failed");

using map_of_five = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five>;
static_assert(std::is_same<brigand::insert<map_of_four, pair_five>, map_of_five>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_five, pair_five>, map_of_five>::value, "insertion failed");

using map_of_six = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five, pair_six>;
static_assert(std::is_same<brigand::insert<map_of_five, pair_six>, map_of_six>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_six, pair_six>, map_of_six>::value, "insertion failed");

using map_of_seven = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five, pair_six, pair_seven>;
static_assert(std::is_same<brigand::insert<map_of_six, pair_seven>, map_of_seven>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_seven, pair_seven>, map_of_seven>::value, "insertion failed");

using map_of_eight = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five, pair_six, pair_seven, pair_eight>;
static_assert(std::is_same<brigand::insert<map_of_seven, pair_eight>, map_of_eight>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_eight, pair_eight>, map_of_eight>::value, "insertion failed");

using map_of_nine = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five, pair_six, pair_seven, pair_eight, pair_nine>;
static_assert(std::is_same<brigand::insert<map_of_eight, pair_nine>, map_of_nine>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_nine, pair_nine>, map_of_nine>::value, "insertion failed");

using map_of_ten = brigand::map<pair_one, pair_two, pair_three, pair_four, pair_five, pair_six, pair_seven, pair_eight, pair_nine, pair_ten>;
static_assert(std::is_same<brigand::insert<map_of_nine, pair_ten>, map_of_ten>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<map_of_ten, pair_ten>, map_of_ten>::value, "insertion failed");

// try exhaustive on big map, we don't do a brigand::fold because we want to test map and insert only we don't want a potential problem in
// fold to interfere with this test
static_assert(std::is_same<brigand::insert<big_map, pair_one>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_two>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_three>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_four>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_five>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_six>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_seven>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_eight>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_nine>, big_map>::value, "insertion failed");
static_assert(std::is_same<brigand::insert<big_map, pair_ten>, big_map>::value, "insertion failed");

0 comments on commit 5add9dd

Please sign in to comment.