What is wrong in the code below?
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <chrono>
namespace data
{
using TimePoint = std::chrono::steady_clock::time_point;
struct Order
{
double price;
double average() const
{
return price;
}
TimePoint updateTime;
};
}
struct DateTag {};
struct PriceTag {};
struct DatePriceTag {};
using DateMember = boost::multi_index::member<data::Order, data::TimePoint, &data::Order::updateTime>;
using PriceMember = boost::multi_index::const_mem_fun<data::Order, double, &data::Order::average>;
using DateKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DateTag>, DateMember>;
using PriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<PriceTag>, PriceMember>;
using DatePriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DatePriceTag>, DateMember, PriceMember>;
using DatePriceDic = boost::multi_index_container<
//data::Order,
std::reference_wrapper<data::Order>,
boost::multi_index::indexed_by<DateKey, PriceKey, DatePriceKey>>;
using DateIndex = DatePriceDic::index<DateTag>::type;
using PriceIndex = DatePriceDic::index<PriceTag>::type;
using DatePriceIndex = DatePriceDic::index<DatePriceTag>::type;
int main()
{
DatePriceDic dic;
data::Order order;
return 0;
}
Compiler error:
>E:\libs\boost_1_78_0\boost/multi_index/detail/ord_index_impl.hpp(1109,1): error C2064: term does not evaluate to a function taking 2 arguments
1>E:\libs\boost_1_78_0\boost/multi_index/detail/ord_index_impl.hpp(1109,1): message : class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
1>E:\libs\boost_1_78_0\boost/multi_index/detail/ord_index_impl.hpp(1089): message : while compiling class template member function 'bool boost::multi_index::detail::ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>::invariant_(void) const'
1> with
1> [
1> KeyFromValue=boost::multi_index::member<`anonymous-namespace'::data::Order,`anonymous-namespace'::data::TimePoint,pointer-to-member(0x8)>,
1> Compare=boost::multi_index::const_mem_fun<`anonymous-namespace'::data::Order,double,double `anonymous-namespace'::data::Order::average(void) const>,
1> SuperMeta=boost::multi_index::detail::nth_layer<3,std::reference_wrapper<`anonymous-namespace'::data::Order>,boost::multi_index::indexed_by<`anonymous-namespace'::DateKey,`anonymous-namespace'::PriceKey,`anonymous-namespace'::DatePriceKey,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<std::reference_wrapper<`anonymous-namespace'::data::Order>>>,
1> TagList=boost::mpl::vector1<`anonymous-namespace'::DatePriceTag>,
1> Category=boost::multi_index::detail::ordered_non_unique_tag,
1> AugmentPolicy=boost::multi_index::detail::null_augment_policy
1> ]
1>E:\libs\boost_1_78_0\boost/multi_index/detail/ord_index_impl.hpp(1123): message : see reference to function template instantiation 'bool boost::multi_index::detail::ordered_index_impl<KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>::invariant_(void) const' being compiled
1> with
1> [
1> KeyFromValue=boost::multi_index::member<`anonymous-namespace'::data::Order,`anonymous-namespace'::data::TimePoint,pointer-to-member(0x8)>,
1> Compare=boost::multi_index::const_mem_fun<`anonymous-namespace'::data::Order,double,double `anonymous-namespace'::data::Order::average(void) const>,
1> SuperMeta=boost::multi_index::detail::nth_layer<3,std::reference_wrapper<`anonymous-namespace'::data::Order>,boost::multi_index::indexed_by<`anonymous-namespace'::DateKey,`anonymous-namespace'::PriceKey,`anonymous-namespace'::DatePriceKey,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<std::reference_wrapper<`anonymous-namespace'::data::Order>>>,
1> TagList=boost::mpl::vector1<`anonymous-namespace'::DatePriceTag>,
1> Category=boost::multi_index::detail::ordered_non_unique_tag,
1> AugmentPolicy=boost::multi_index::detail::null_augment_policy
1> ]
compiler: Microsoft (R) C/C Optimizing Compiler Version 19.31.31104 for x86
boost version: boost_1_78_0
CodePudding user response:
Adding to your own answer, if you are using C 17 or newer, boost::multi_index::key
can get you a somewhat terser syntax:
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key.hpp>
#include <chrono>
namespace data
{
using TimePoint = std::chrono::steady_clock::time_point;
struct Order
{
double price;
double average() const
{
return price;
}
TimePoint updateTime;
};
}
struct DateTag {};
struct PriceTag {};
struct DatePriceTag {};
constexpr auto DateMember = &data::Order::updateTime;
constexpr auto PriceMember = &data::Order::average;
using DateKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DateTag>, boost::multi_index::key<DateMember>>;
using PriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<PriceTag>, boost::multi_index::key<PriceMember>>;
using DatePriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DatePriceTag>, boost::multi_index::key<DateMember, PriceMember>>;
using DatePriceDic = boost::multi_index_container<
//data::Order,
std::reference_wrapper<data::Order>,
boost::multi_index::indexed_by<DateKey, PriceKey, DatePriceKey>>;
using DateIndex = DatePriceDic::index<DateTag>::type;
using PriceIndex = DatePriceDic::index<PriceTag>::type;
using DatePriceIndex = DatePriceDic::index<DatePriceTag>::type;
int main()
{
DatePriceDic dic;
data::Order order;
return 0;
}
CodePudding user response:
I forgot boost::multi_index::composite_key
:
using DatePriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DatePriceTag>,
boost::multi_index::composite_key<data::Order, DateMember, PriceMember>>;
CodePudding user response:
Let me also add that you don't really need DateIndex
as DatePriceIndex
can do its job (apart from supporting composite keys on date and price):
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key.hpp>
#include <chrono>
namespace data
{
using TimePoint = std::chrono::steady_clock::time_point;
struct Order
{
double price;
double average() const
{
return price;
}
TimePoint updateTime;
};
}
struct PriceTag {};
struct DatePriceTag {};
constexpr auto DateMember = &data::Order::updateTime;
constexpr auto PriceMember = &data::Order::average;
using DatePriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<DatePriceTag>, boost::multi_index::key<DateMember, PriceMember>>;
using PriceKey = boost::multi_index::ordered_non_unique<boost::multi_index::tag<PriceTag>, boost::multi_index::key<PriceMember>>;
using DatePriceDic = boost::multi_index_container<
//data::Order,
std::reference_wrapper<data::Order>,
boost::multi_index::indexed_by<DatePriceKey, PriceKey>>;
using DatePriceIndex = DatePriceDic::index<DatePriceTag>::type;
using PriceIndex = DatePriceDic::index<PriceTag>::type;
#include <iostream>
int main()
{
using namespace std::literals;
auto now=std::chrono::steady_clock::now();
data::Order dat[]={
{100.0, now},
{100.0, now-24h},
{200.0, now-24h},
};
DatePriceDic dic;
for(auto& o: dat) dic.insert(std::ref(o));
std::cout<<dic.count(now-24h)<<"\n"; // prints 2
std::cout<<dic.count(std::make_tuple(now-24h,100.0))<<"\n"; // prints 1
return 0;
}