c++boostoperator-overloadingboost-multi-index

How to overload the [] operator for boost::multi_index_container


I need to overload the [] operator for boost::multi_index_container. It would look like something like this :

template<typename T>
using my_set = boost::multi_index_container<
    T,
    boost::multi_index::indexed_by<
        boost::multi_index::sequenced<>,
        boost::multi_index::ordered_unique<boost::multi_index::identity<T>>
    >
>;

template<typename T>
T operator[](const my_set &s, const size_t &t){
    auto it=s.get<0>.begin();
    advance(it, t);
    return *it;
}

I tried but I get this error :

error: ‘T operator[](boost::multi_index::multi_index_container<T, boost::multi_index::indexed_by<boost::multi_index::sequenced<>, boost::multi_index::ordered_unique<boost::multi_index::identity<Value> > > >&, int&)’ must be a nonstatic member function
 \> &s, int &t){

Is there any way I can do this ?

I want to do this because I had a vector and I need to insert unique elements in it. I used find to know if the element was already in my vector then inserted it if it wasn't. But the linear complexity of find on a vector bothered me, I thought of using a set but I want to keep the elements in the insertion order.

Using a multi_index_container allows me to keep the insertion index with s.get<0> but will also allow me to have unique elements in it

I hope everything's clear.


Solution

  • On first read I thought you wanted to have something like std::map::operator[], but that's a bad idea, see below.

    On second read I noticed that you ONLY want random-access to the sequenced index. sequenced has list-like semantics.

    You're in luck, random-access indexes already exist! Just use it instead:

    Live On Compiler Explorer

    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/ordered_index.hpp>
    #include <boost/multi_index/random_access_index.hpp>
    #include <fmt/ranges.h>
    
    namespace bmi = boost::multi_index;
    
    template <typename T>
    using my_set = bmi::multi_index_container<
        T,
        bmi::indexed_by<bmi::random_access<>,
                        bmi::ordered_unique<bmi::identity<T>>>>;
    
    int main() {
        my_set<int> s{1, 7, 7, 8, -4, 22, 1, 5, 4};
    
        fmt::print("Original: {}\n", s);
        fmt::print("Same:     {}\n", s.get<0>());
        fmt::print("Ordered:  {}\n", s.get<1>());
        fmt::print("Element 2: {}\n", s[2]);
    }
    

    Prints:

    Original: [1, 7, 8, -4, 22, 5, 4]
    Same:     [1, 7, 8, -4, 22, 5, 4]
    Ordered:  {-4, 1, 4, 5, 7, 8, 22}
    Element 2: 8
    

    OLD answer: Why Associative operator[] is a bad idea

    "I need to overload the [] operator for boost::multi_index_container" - actually, you don't. You may want to.

    Here's why it's not a good idea.

    Boost MultiIndex shares the second reason for not providing these operations. However, regardless of that, all values are always const in a multi-index container.