Skip to content

Commit

Permalink
optimized map::at
Browse files Browse the repository at this point in the history
* optimized map::at

* fixes lookup/map::at with C-style array type

* [msvc] fixes lookup

* [msvc] fixes lookup
  • Loading branch information
jonathanpoelen authored and edouarda committed Apr 3, 2016
1 parent 7d4107a commit dfe4624
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 114 deletions.
135 changes: 21 additions & 114 deletions brigand/sequences/map.hpp
Expand Up @@ -13,8 +13,16 @@
namespace brigand
{

namespace lazy
{
template <typename M, typename K>
struct lookup
: decltype(M::at(type_<K>{}))
{};
}

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

namespace detail
{
Expand Down Expand Up @@ -47,128 +55,27 @@ namespace detail
struct map_impl<>
{
template <typename U>
static no_such_type_ at(U);
static type_<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> : map_inserter<T0>
{
static typename T0::second_type at(type_<typename T0::first_type>);

template <typename U>
static no_such_type_ at(U);
};

template <class T0, class 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>);

template <typename U>
static no_such_type_ at(U);
};

template <class T0, class T1, class 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>);
static typename T2::second_type at(type_<typename T2::first_type>);

template <typename U>
static no_such_type_ at(U);
};

template <class T0, class T1, class T2, class 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>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);

template <typename U>
static no_such_type_ at(U);
};

template <class T0, class T1, class T2, class T3, class 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>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);
static typename T4::second_type at(type_<typename T4::first_type>);

template <typename U>
static no_such_type_ at(U);
};

template <class T0, class T1, class T2, class T3, class T4, class 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>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);
static typename T4::second_type at(type_<typename T4::first_type>);
static typename T5::second_type at(type_<typename T5::first_type>);

template <typename U>
static no_such_type_ at(U);
};

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> : map_inserter<T0, T1, T2, T3, T4, T5, T6>
template <class... Ts>
struct map_impl : map_inserter<Ts...>
{
static typename T0::second_type at(type_<typename T0::first_type>);
static typename T1::second_type at(type_<typename T1::first_type>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);
static typename T4::second_type at(type_<typename T4::first_type>);
static typename T5::second_type at(type_<typename T5::first_type>);
static typename T6::second_type at(type_<typename T6::first_type>);
private:
struct Pack : pair<typename Ts::first_type, Ts>... {};

template <typename U>
static no_such_type_ at(U);
};
template<class K, class P>
static type_<typename P::second_type> at_impl(pair<K,P>*);

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> : 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>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);
static typename T4::second_type at(type_<typename T4::first_type>);
static typename T5::second_type at(type_<typename T5::first_type>);
static typename T6::second_type at(type_<typename T6::first_type>);
static typename T7::second_type at(type_<typename T7::first_type>);
public:
template<class K>
static decltype(at_impl<K>(static_cast<Pack*>(nullptr))) at(type_<K>);

template <typename U>
static no_such_type_ at(U);
};


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...> : 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>);
static typename T2::second_type at(type_<typename T2::first_type>);
static typename T3::second_type at(type_<typename T3::first_type>);
static typename T4::second_type at(type_<typename T4::first_type>);
static typename T5::second_type at(type_<typename T5::first_type>);
static typename T6::second_type at(type_<typename T6::first_type>);
static typename T7::second_type at(type_<typename T7::first_type>);

template <typename U>
static decltype(map_impl<T...>::at(U{})) at(U);
template<class K>
static type_<no_such_type_> at(K);
};

// if you have a "class already a base" error message, it means you have defined a map with the same key present more
Expand Down
2 changes: 2 additions & 0 deletions test/map_test.cpp
Expand Up @@ -10,6 +10,8 @@ static_assert(brigand::detail::has_at_method<brigand::map<>>::value, "at not det
// empty maps are allowed
static_assert(brigand::size<brigand::map<>>::value == 0, "empty map isn't empty");
static_assert(std::is_same<brigand::lookup<brigand::map<>, int>, brigand::no_such_type_>::value, "should find no such type in empty map");
static_assert(std::is_same<brigand::lookup<brigand::map<brigand::pair<int, int[1]>>, int>, int[1]>::value, "should be int[1]");
static_assert(std::is_same<brigand::lookup<brigand::map<brigand::pair<int[1], int>>, int[1]>, int>::value, "should be int");

using map_test = brigand::map<brigand::pair<int, bool>, brigand::pair<char, int>>;

Expand Down

0 comments on commit dfe4624

Please sign in to comment.