#include #include #include #include #include #include #include #include #include #include #include namespace te = boost::type_erasure; namespace fusion = boost::fusion; namespace mpl = boost::mpl; template struct at_key { static Reference apply(Sequence& sequence) { return fusion::at_key(sequence); } }; template struct any_map { typedef mpl::vector< te::relaxed_match, te::copy_constructible<>, typename mpl::transform< Properties, at_key< te::_self, mpl::first, mpl::second > >::type > concepts; typedef te::any< concepts, typename mpl::if_::type > type; }; struct key1 {}; // body needs to be defined for Boost.TypeErasure struct key2 {}; typedef boost::fusion::map< boost::fusion::pair, boost::fusion::pair > map2; typedef any_map< mpl::vector< mpl::pair, mpl::pair > >::type any_map2; typedef any_map< mpl::vector< mpl::pair > >::type any_map1; typedef any_map>>::concepts any_map1_concepts; typedef any_map< mpl::vector< mpl::pair >, mpl::true_ >::type any_map1_ref; struct type_info_cmp { bool operator()(const std::type_info* t1, const std::type_info* t2) const { return t1->before(*t2) != 0; } }; typedef std::map, type_info_cmp> binding_map; typedef std::map> binding_map_ptr_cmp; int main() { const int N = 1000000; const int repeats = 100; std::vector any_map2_vec(N); for(int i = 0; i < N; ++i) { map2 a; fusion::at_key(a) = std::rand() % 100; any_map2_vec[i] = a; } { boost::progress_timer t; int sum = 0; for(int i = 0; i < repeats; ++i) { BOOST_FOREACH(auto& x, any_map2_vec) { sum += te::call(at_key(), x); } } std::cout << "any_map2: " << sum << std::endl; } { boost::progress_timer t; int sum = 0; for(int i = 0; i < repeats; ++i) { BOOST_FOREACH(auto& x, any_map2_vec) { any_map1 y(x); sum += te::call(at_key(), y); } } std::cout << "any_map1_ref: " << sum << std::endl; } { boost::progress_timer t; int sum = 0; for(int i = 0; i < repeats; ++i) { mpl::map> placeholder_map; te::binding binding(te::binding_of(any_map2_vec[0]), placeholder_map); BOOST_FOREACH(auto& x, any_map2_vec) { any_map1_ref y(x, binding); sum += te::call(at_key(), y); } } std::cout << "any_map1_ref (single binding): " << sum << std::endl; } { boost::progress_timer t; int sum = 0; for(int i = 0; i < repeats; ++i) { mpl::map> placeholder_map; binding_map bindings; bindings[&te::typeid_of(any_map2_vec[0])] = te::binding(te::binding_of(any_map2_vec[0]), placeholder_map); BOOST_FOREACH(auto& x, any_map2_vec) { // real code would need to check if the binding is already cached and create it if not any_map1_ref y(x, bindings[&te::typeid_of(x)]); sum += te::call(at_key(), y); } } std::cout << "any_map1_ref (correct map lookup): " << sum << std::endl; } { boost::progress_timer t; int sum = 0; for(int i = 0; i < repeats; ++i) { mpl::map> placeholder_map; binding_map_ptr_cmp bindings; bindings[&te::typeid_of(any_map2_vec[0])] = te::binding(te::binding_of(any_map2_vec[0]), placeholder_map); BOOST_FOREACH(auto& x, any_map2_vec) { // real code would need to check if the binding is already cached and create it if not any_map1_ref y(x, bindings[&te::typeid_of(x)]); sum += te::call(at_key(), y); } } std::cout << "any_map1_ref (fast map lookup): " << sum << std::endl; } return 0; }