Home > Enterprise >  Can't compile boost::multi_index_container
Can't compile boost::multi_index_container

Time:02-20

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):

Live Coliru Demo

#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;
}
  • Related