0

I have not worked with c++ in a few years and am struggling with implementing a boost multi_index container. I've generated a toy that demonstrates my problem here: http://cpp.sh/6q4nb, and (after some typing) I've recreated that code here:

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>

class Placeholder {
    public:
        const uint64_t& getPlaceholderTime( void )  const   { return ph_time; }
        const std::string& getPlaceholderId( void ) const   { return ph_id; }

    private:
        uint64_t ph_time;
        std::string ph_id;
};

struct IndexByPlaceholderId { };

typedef boost::multi_index_container<
    Placeholder,
    boost::multi_index::indexed_by
    <boost::multi_index::ordered_non_unique< boost::multi_index::identity<Placeholder> >
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::const_mem_fun<
            Placeholder,
            const uint64_t&,
            &Placeholder::getPlaceholderTime
        >
    >
    ,boost::multi_index::ordered_non_unique<
        boost::multi_index::tag<IndexByPlaceholderId>,
        boost::multi_index::const_mem_fun<
            Placeholder,
            const std::string&,
            &Placeholder::getPlaceholderId
        >
    >
    >
> currentPlaceholderDatabase;

int main()
{
    currentPlaceholderDatabase currentDb;

    std::string someString = "something";

    volatile auto result = currentDb.get<IndexByPlaceholderId>().find( someString );
    if( result == currentDb.get<IndexByPlaceholderId>().end() )
    {
        std::cout << "NOT FOUND\n";
    }
    else
    {
        std::cout << "FOUND!!\n";
    }
}

Essentially, I'm searching for an element using find() and then testing if that element is found or not using operator==. The search I'm doing is using index tagging as explained in the boost documentation. If it is required that I generate an operator== for this container, can someone demonstrate how to do so as I can't find a clear example in the documentation?

The error I get is:

57:14: error: no match for 'operator==' (operand types are 'volatile boost::multi_index::detail::bidir_node_iterator<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<Placeholder, std::allocator<Placeholder> > > >' and 'boost::multi_index::detail::ordered_index<boost::multi_index::const_mem_fun<Placeholder, const std::basic_string<char>&, &Placeholder::getPlaceholderId>, std::less<const std::basic_string<char> >, boost::multi_index::detail::nth_layer<3, Placeholder, boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::identity<Placeholder> >, boost::multi_index::ordered_non_unique<boost::multi_index::const_mem_fun<Placeholder, const long unsigned int&, &Placeholder::getPlaceholderTime> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<IndexByPlaceholderId>, boost::multi_index::const_mem_fun<Placeholder, const std::basic_string<char>&, &Placeholder::getPlaceholderId> > >, std::allocator<Placeholder> >, boost::mpl::v_item<IndexByPlaceholderId, boost::mpl::vector0<mpl_::na>, 0>, boost::multi_index::detail::ordered_non_unique_tag>::iterator {aka boost::multi_index::detail::bidir_node_iterator<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<Placeholder, std::allocator<Placeholder> > > >}')

Followed by the usual long list of candidates due to c++ template options.

Joaquín M López Muñoz
  • 5,243
  • 1
  • 15
  • 20
highbandwidth
  • 156
  • 1
  • 6
  • Questions seeking debugging help must contain the code *within the question itself*. – JaMiT Mar 14 '20 at 18:17
  • Updated to include code in the question. – highbandwidth Mar 14 '20 at 18:41
  • Why did you declare `result` to be `volatile`? – JaMiT Mar 14 '20 at 19:00
  • Apologies, didn't notice this question/comment - result was declared volatile to try and resolve a error: binding reference of type 'X&' to 'const value_type {aka const X}' discards qualifiers when I try and pass *result in a subsequent method. I thought this was the consequence of auto making result const when it shouldn't be because in the subsequent method (not shown here) I need to modify ph_time. Further, I mistakenly didn't reproduce ph_time's type in my toy above correctly. It should have been 'mutable uint64_t ph_time'. – highbandwidth Mar 15 '20 at 16:24

1 Answers1

2

The error message unfortunately has the appearance of gibberish because of the multiple levels of templating involved. This is complicated by the way Boost.MultiIndex uses different return types for find() and end(), expecting either implicit conversions or function overloads to hide that detail from the programmer. Fortunately, the solution is simple: remove volatile.

Much like a const variable cannot be used to initialize a non-const reference, a volatile variable cannot be used to initialize a non-volatile reference. The various declarations that are supposed to make the Boost magic happen do not use volatile, so when you declared result to be volatile, it was left out in the cold.

There should be no harm caused by removing volatile in this case. Your result variable is not being shared with other processes, so volatile accomplishes nothing other than potentially slowing down your code. If you thought you had a reason for using volatile, you may want to read Why does volatile exist? In particular, volatile does not prevent const. Even though they look incompatible at first, a variable can be both const (cannot be modified by the current code) and volatile (can be modified by something external to the program).

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • Yes, I see now how the volatile led to this situation. I added the volatile as a guess that auto was causing the type to be const and I'm using result in a method call that is causing an error of binding reference of type X& to const value_type {aka X} discards qualifers. That is the original problem that I'm back to now. I'll post a separate question about that if I'm still unable to solve it... – highbandwidth Mar 15 '20 at 15:37