239 changes: 238 additions & 1 deletion include/boost/multi_index/composite_key.hpp
@@ -1,4 +1,4 @@
/* Copyright 2003-2013 Joaquin M Lopez Munoz.
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -39,6 +39,11 @@
#include <boost/type_traits/is_convertible.hpp>
#endif

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/multi_index/detail/cons_stdtuple.hpp>
#endif

/* A composite key stores n key extractors and "computes" the
* result on a given value as a packed reference to the value and
* the composite key itself. Actual invocations to the component
Expand Down Expand Up @@ -712,6 +717,55 @@ inline bool operator==(
y.value,detail::generic_operator_equal_tuple());
}

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename CompositeKey,typename... Values>
inline bool operator==(
const composite_key_result<CompositeKey>& x,
const std::tuple<Values...>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value==
std::tuple_size<key_tuple>::value);

return detail::equal_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,detail::generic_operator_equal_tuple
>::compare(
x.composite_key.key_extractors(),x.value,
detail::make_cons_stdtuple(y),detail::generic_operator_equal_tuple());
}

template<typename CompositeKey,typename... Values>
inline bool operator==(
const std::tuple<Values...>& x,
const composite_key_result<CompositeKey>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value==
std::tuple_size<key_tuple>::value);

return detail::equal_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,detail::generic_operator_equal_tuple
>::compare(
detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
y.value,detail::generic_operator_equal_tuple());
}
#endif

/* < */

template<typename CompositeKey1,typename CompositeKey2>
Expand Down Expand Up @@ -776,6 +830,47 @@ inline bool operator<(
y.value,detail::generic_operator_less_tuple());
}

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename CompositeKey,typename... Values>
inline bool operator<(
const composite_key_result<CompositeKey>& x,
const std::tuple<Values...>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,detail::generic_operator_less_tuple
>::compare(
x.composite_key.key_extractors(),x.value,
detail::make_cons_stdtuple(y),detail::generic_operator_less_tuple());
}

template<typename CompositeKey,typename... Values>
inline bool operator<(
const std::tuple<Values...>& x,
const composite_key_result<CompositeKey>& y)
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,detail::generic_operator_less_tuple
>::compare(
detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
y.value,detail::generic_operator_less_tuple());
}
#endif

/* rest of comparison operators */

#define BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(t1,t2,a1,a2) \
Expand Down Expand Up @@ -820,6 +915,23 @@ BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
composite_key_result<CompositeKey>
)

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
typename CompositeKey,
typename... Values,
composite_key_result<CompositeKey>,
std::tuple<Values...>
)

BOOST_MULTI_INDEX_CK_COMPLETE_COMP_OPS(
typename CompositeKey,
typename... Values,
std::tuple<Values...>,
composite_key_result<CompositeKey>
)
#endif

/* composite_key_equal_to */

template
Expand Down Expand Up @@ -920,6 +1032,59 @@ struct composite_key_equal_to:
key_tuple,key_eq_tuple
>::compare(x,y.composite_key.key_extractors(),y.value,key_eqs());
}

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename CompositeKey,typename... Values>
bool operator()(
const composite_key_result<CompositeKey>& x,
const std::tuple<Values...>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value<=
tuples::length<key_eq_tuple>::value&&
tuples::length<key_extractor_tuple>::value==
std::tuple_size<key_tuple>::value);

return detail::equal_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,key_eq_tuple
>::compare(
x.composite_key.key_extractors(),x.value,
detail::make_cons_stdtuple(y),key_eqs());
}

template<typename CompositeKey,typename... Values>
bool operator()(
const std::tuple<Values...>& x,
const composite_key_result<CompositeKey>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
std::tuple_size<key_tuple>::value<=
tuples::length<key_eq_tuple>::value&&
std::tuple_size<key_tuple>::value==
tuples::length<key_extractor_tuple>::value);

return detail::equal_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,key_eq_tuple
>::compare(
detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
y.value,key_eqs());
}
#endif
};

/* composite_key_compare */
Expand Down Expand Up @@ -1042,6 +1207,59 @@ struct composite_key_compare:
key_tuple,key_comp_tuple
>::compare(x,y.composite_key.key_extractors(),y.value,key_comps());
}

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename CompositeKey,typename... Values>
bool operator()(
const composite_key_result<CompositeKey>& x,
const std::tuple<Values...>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
tuples::length<key_extractor_tuple>::value<=
tuples::length<key_comp_tuple>::value||
std::tuple_size<key_tuple>::value<=
tuples::length<key_comp_tuple>::value);

return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,key_comp_tuple
>::compare(
x.composite_key.key_extractors(),x.value,
detail::make_cons_stdtuple(y),key_comps());
}

template<typename CompositeKey,typename... Values>
bool operator()(
const std::tuple<Values...>& x,
const composite_key_result<CompositeKey>& y)const
{
typedef typename CompositeKey::key_extractor_tuple key_extractor_tuple;
typedef typename CompositeKey::value_type value_type;
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
std::tuple_size<key_tuple>::value<=
tuples::length<key_comp_tuple>::value||
tuples::length<key_extractor_tuple>::value<=
tuples::length<key_comp_tuple>::value);

return detail::compare_ckey_cval<
key_extractor_tuple,value_type,
cons_key_tuple,key_comp_tuple
>::compare(
detail::make_cons_stdtuple(x),y.composite_key.key_extractors(),
y.value,key_comps());
}
#endif
};

/* composite_key_hash */
Expand Down Expand Up @@ -1099,6 +1317,25 @@ struct composite_key_hash:
key_tuple,key_hasher_tuple
>::hash(x,key_hash_functions());
}

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename... Values>
std::size_t operator()(const std::tuple<Values...>& x)const
{
typedef std::tuple<Values...> key_tuple;
typedef typename detail::cons_stdtuple_ctor<
key_tuple>::result_type cons_key_tuple;

BOOST_STATIC_ASSERT(
std::tuple_size<key_tuple>::value==
tuples::length<key_hasher_tuple>::value);

return detail::hash_cval<
cons_key_tuple,key_hasher_tuple
>::hash(detail::make_cons_stdtuple(x),key_hash_functions());
}
#endif
};

/* Instantiations of the former functors with "natural" basic components:
Expand Down
93 changes: 93 additions & 0 deletions include/boost/multi_index/detail/cons_stdtuple.hpp
@@ -0,0 +1,93 @@
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/

#ifndef BOOST_MULTI_INDEX_DETAIL_CONS_STDTUPLE_HPP
#define BOOST_MULTI_INDEX_DETAIL_CONS_STDTUPLE_HPP

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/tuple/tuple.hpp>
#include <tuple>

namespace boost{

namespace multi_index{

namespace detail{

/* std::tuple wrapper providing the cons-based interface of boost::tuple for
* composite_key interoperability.
*/

template<typename StdTuple,std::size_t N>
struct cons_stdtuple;

struct cons_stdtuple_ctor_terminal
{
typedef boost::tuples::null_type result_type;

template<typename StdTuple>
static result_type create(const StdTuple&)
{
return boost::tuples::null_type();
}
};

template<typename StdTuple,std::size_t N>
struct cons_stdtuple_ctor_normal
{
typedef cons_stdtuple<StdTuple,N> result_type;

static result_type create(const StdTuple& t)
{
return result_type(t);
}
};

template<typename StdTuple,std::size_t N=0>
struct cons_stdtuple_ctor:
boost::mpl::if_c<
N<std::tuple_size<StdTuple>::value,
cons_stdtuple_ctor_normal<StdTuple,N>,
cons_stdtuple_ctor_terminal
>::type
{};

template<typename StdTuple,std::size_t N>
struct cons_stdtuple
{
typedef typename std::tuple_element<N,StdTuple>::type head_type;
typedef cons_stdtuple_ctor<StdTuple,N+1> tail_ctor;
typedef typename tail_ctor::result_type tail_type;

cons_stdtuple(const StdTuple& t_):t(t_){}

const head_type& get_head()const{return std::get<N>(t);}
tail_type get_tail()const{return tail_ctor::create(t);}

const StdTuple& t;
};

template<typename StdTuple>
typename cons_stdtuple_ctor<StdTuple>::result_type
make_cons_stdtuple(const StdTuple& t)
{
return cons_stdtuple_ctor<StdTuple>::create(t);
}

} /* namespace multi_index::detail */

} /* namespace multi_index */

} /* namespace boost */

#endif
199 changes: 140 additions & 59 deletions test/test_composite_key.cpp
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for composite_key.
*
* Copyright 2003-2013 Joaquin M Lopez Munoz.
* Copyright 2003-2014 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -18,6 +18,9 @@
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>

using namespace boost::multi_index;
using namespace boost::tuples;
Expand Down Expand Up @@ -54,6 +57,46 @@ struct composite_key_result_length
>::value);
};

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
struct is_boost_tuple_helper
{
typedef char yes;
struct no{char m[2];};

static no test(void*);

template<BOOST_PP_ENUM_PARAMS(10,typename T)>
static yes test(boost::tuple<BOOST_PP_ENUM_PARAMS(10,T)>*);
};

template<typename T>
struct is_boost_tuple
{
typedef is_boost_tuple_helper helper;

BOOST_STATIC_CONSTANT(bool,
value=(
sizeof(helper::test((T*)0))==
sizeof(typename helper::yes)));
};

template<typename T>
struct composite_object_length
{
typedef typename boost::mpl::if_c<
is_composite_key_result<T>::value,
composite_key_result_length<T>,
typename boost::mpl::if_c<
is_boost_tuple<T>::value,
boost::tuples::length<T>,
std::tuple_size<T>
>::type
>::type type;

BOOST_STATIC_CONSTANT(int,value=type::value);
};
#else
template<typename T>
struct composite_object_length
{
Expand All @@ -65,6 +108,7 @@ struct composite_object_length

BOOST_STATIC_CONSTANT(int,value=type::value);
};
#endif

template<typename CompositeKeyResult,typename T2>
struct comparison_equal_length
Expand Down Expand Up @@ -289,7 +333,33 @@ struct xystr
std::string str;
};

void test_composite_key()
#define TUPLE_MAKER_CREATE(z,n,tuple) \
template<BOOST_PP_ENUM_PARAMS(n,typename T)> \
static tuple<BOOST_PP_ENUM_PARAMS(n,T)> \
create(BOOST_PP_ENUM_BINARY_PARAMS(n,T,t)){ \
return tuple<BOOST_PP_ENUM_PARAMS(n,T)>( \
BOOST_PP_ENUM_PARAMS(n,t)); \
}

#define DEFINE_TUPLE_MAKER(name,tuple) \
struct name \
{ \
static tuple<> create(){return tuple<>();} \
BOOST_PP_REPEAT_FROM_TO(1,5,TUPLE_MAKER_CREATE,tuple) \
};

DEFINE_TUPLE_MAKER(boost_tuple_maker,boost::tuple)

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
DEFINE_TUPLE_MAKER(std_tuple_maker,std::tuple)
#endif

#undef DEFINE_TUPLE_MAKER
#undef TUPLE_MAKER_CREATE

template<typename TupleMaker>
void test_composite_key_template()
{
typedef composite_key<
xyz,
Expand Down Expand Up @@ -322,12 +392,12 @@ void test_composite_key()
mc1.find(mc1.key_extractor()(xyz(1,0,0))))==4);
BOOST_TEST(
std::distance(
mc1.find(make_tuple(0,0,0)),
mc1.find(make_tuple(1,0,0)))==4);
mc1.find(TupleMaker::create(0,0,0)),
mc1.find(TupleMaker::create(1,0,0)))==4);
BOOST_TEST(
std::distance(
mc1.lower_bound(make_tuple(0,0)),
mc1.upper_bound(make_tuple(1,0)))==6);
mc1.lower_bound(TupleMaker::create(0,0)),
mc1.upper_bound(TupleMaker::create(1,0)))==6);

#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
BOOST_TEST(
Expand All @@ -354,16 +424,16 @@ void test_composite_key()
BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0))));
BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0))));

BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0,1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0)));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1)));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1)));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0,1)));

typedef composite_key_result_less<ckey_t1::result_type> ckey_comp_t1;
typedef composite_key_result_equal_to<ckey_t1::result_type> ckey_eq_t1;
Expand All @@ -375,22 +445,22 @@ void test_composite_key()
BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1,eq1));
BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1,eq1));

BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp1));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp1));

#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),0,cp1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),1,cp1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),-1,cp1));
#endif

BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,1),cp1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,-1),cp1));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp1,eq1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp1,eq1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp1,eq1));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp1));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp1,eq1));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp1,eq1));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp1,eq1));

typedef composite_key_result_greater<ckey_t1::result_type> ckey_comp_t2;

Expand All @@ -400,15 +470,15 @@ void test_composite_key()
BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2));

BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(-1),cp2));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp2));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp2));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(-1),cp2));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp2));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp2));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp2));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp2));

typedef composite_key_equal_to<
modulo_equal,
Expand Down Expand Up @@ -444,18 +514,18 @@ void test_composite_key()
BOOST_TEST(!eq2(ck1(xyz(2,2,0)),ck1(xyz(0,0,0))));
BOOST_TEST( eq2(ck1(xyz(2,3,0)),ck1(xyz(0,0,0))));

BOOST_TEST( eq2(make_tuple(0,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(0,1,0)) ,make_tuple(0,0,0)));
BOOST_TEST(!eq2(make_tuple(0,2,0),ck1(xyz(0,0,0))));
BOOST_TEST( eq2(ck1(xyz(0,3,0)) ,make_tuple(0,0,0)));
BOOST_TEST(!eq2(make_tuple(1,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(1,1,0)) ,make_tuple(0,0,0)));
BOOST_TEST(!eq2(make_tuple(1,2,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(1,3,0)) ,make_tuple(0,0,0)));
BOOST_TEST( eq2(make_tuple(2,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(2,1,0)) ,make_tuple(0,0,0)));
BOOST_TEST(!eq2(make_tuple(2,2,0),ck1(xyz(0,0,0))));
BOOST_TEST( eq2(ck1(xyz(2,3,0)) ,make_tuple(0,0,0)));
BOOST_TEST( eq2(TupleMaker::create(0,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(0,1,0)) ,TupleMaker::create(0,0,0)));
BOOST_TEST(!eq2(TupleMaker::create(0,2,0),ck1(xyz(0,0,0))));
BOOST_TEST( eq2(ck1(xyz(0,3,0)) ,TupleMaker::create(0,0,0)));
BOOST_TEST(!eq2(TupleMaker::create(1,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(1,1,0)) ,TupleMaker::create(0,0,0)));
BOOST_TEST(!eq2(TupleMaker::create(1,2,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(1,3,0)) ,TupleMaker::create(0,0,0)));
BOOST_TEST( eq2(TupleMaker::create(2,0,0),ck1(xyz(0,0,0))));
BOOST_TEST(!eq2(ck1(xyz(2,1,0)) ,TupleMaker::create(0,0,0)));
BOOST_TEST(!eq2(TupleMaker::create(2,2,0),ck1(xyz(0,0,0))));
BOOST_TEST( eq2(ck1(xyz(2,3,0)) ,TupleMaker::create(0,0,0)));

typedef composite_key_compare<
std::less<int>,
Expand All @@ -480,15 +550,15 @@ void test_composite_key()
BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3));

BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(-1),cp3));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,-1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,1),cp3));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),make_tuple(0,0,0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),make_tuple(0,0,1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),make_tuple(0,0,-1),cp3));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp3));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp3));
BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp3));
BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp3));
BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp3));

typedef composite_key<
xyz,
Expand Down Expand Up @@ -540,8 +610,9 @@ void test_composite_key()
mc2.insert(xyz(1,1,1));

BOOST_TEST(mc2.size()==8);
BOOST_TEST(mc2.find(make_tuple(0,0,1))->z==1);
BOOST_TEST(ck1(*(mc2.find(make_tuple(1,0,1))))==make_tuple(1,0,1));
BOOST_TEST(mc2.find(TupleMaker::create(0,0,1))->z==1);
BOOST_TEST(ck1(*(mc2.find(TupleMaker::create(1,0,1))))==
TupleMaker::create(1,0,1));

typedef composite_key<
xystr,
Expand Down Expand Up @@ -573,10 +644,10 @@ void test_composite_key()

BOOST_TEST(
ch1(ck6(xystr(0,0,"hello")))==
ch1(boost::make_tuple(std::string("hello"),0,0)));
ch1(TupleMaker::create(std::string("hello"),0,0)));
BOOST_TEST(
ch1(ck6(xystr(4,5,"world")))==
ch1(boost::make_tuple(std::string("world"),4,5)));
ch1(TupleMaker::create(std::string("world"),4,5)));

typedef boost::hash<composite_key_result<ckey_t3> > ckeyres_hash_t;

Expand All @@ -587,3 +658,13 @@ void test_composite_key()
BOOST_TEST(
ch1(ck6(xystr(4,5,"world")))==crh(ck6(xystr(4,5,"world"))));
}

void test_composite_key()
{
test_composite_key_template<boost_tuple_maker>();

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
test_composite_key_template<std_tuple_maker>();
#endif
}