2

I have a number of strings and their bitset equivalents. I need to be able to look up equivalents in both directions, i.e. "str to bitset" and "bitset to str". I believe boost-bimap would be the right container for this job.

I managed to get this to work with strings and integers but my string / bitset bimap does not compile. I am using VS2019 with the latest boost release.

Integer example works:

#include <boost/bimap.hpp>
#include <string>
#include <iostream>

int main()
{
    typedef boost::bimap<std::string, int> bimap_str_int_t;

    bimap_str_int_t bimap1;
    bimap1.insert(bimap_str_int_t::value_type("A", 1));
    std::cout << bimap1.left.at("A") << '\n';  //prints 1
    std::cout << bimap1.right.at(1) << '\n';   // prints A
}

Bitset example fails to compile:

#include <boost/bimap.hpp>
#include <string>
#include <iostream>
#include <bitset>

int main()
{
    typedef std::bitset<3> bitset_t;
    typedef boost::bimap<std::string, bitset_t> bimap_str_bitset_t;

    bimap_str_bitset_t bimap2;
    bitset_t bits{ "010" };

    bimap2.insert(bimap_str_bitset_t::value_type("A", bits));
    std::cout << bimap2.left.at("A") << '\n';
    std::cout << bimap2.right.at(bits) << '\n';
}

The bitset example creates the following compiler error:

boost_test.cpp(20): message : see reference to class template instantiation 'boost::bimaps::bimap' being compiled

I am not sure how to fix this and would greatly appreciate any hints.

W.R.
  • 23
  • 3

1 Answers1

1

The issue is that std::bitset has no operator< - one of the requirements of any STL-like ordered collection.

To fix this, you need to supply a comparison function - here's one way you might try:

#include <boost/bimap.hpp>
#include <string>
#include <iostream>
#include <bitset>

typedef std::bitset<3> bitset_t;
struct compare_bitset {
    bool operator()(const bitset_t& x, const bitset_t& y) const {
        return x.to_ulong() < y.to_ulong();
    }
};

int main()
{
    using bitset_set = boost::bimaps::set_of<bitset_t, compare_bitset>;
    typedef boost::bimap < std::string, bitset_set> bimap_str_bitset_t;

    bimap_str_bitset_t bimap2;
    bitset_t bits{ "010" };

    bimap2.insert(bimap_str_bitset_t::value_type("A", bits));
    std::cout << bimap2.left.at("A") << '\n';
    std::cout << bimap2.right.at(bits) << '\n';
}
Ayjay
  • 3,413
  • 15
  • 20
  • Thank you @Ayjay, that works well. Appreciate the quick reply. Out of curiosity, is this something I should have been able to gather from the error message? – W.R. Oct 12 '19 at 06:53
  • The first line of the compile error I got from your program was `error C2678: binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion) with [ _Ty=std::bitset<3>]`. To be honest, I mostly just guessed that was the issue since I was pretty sure bitset didn't have an `operator<` and knew that this was a requirement of any ordered collection. The good news is that in C++20, concepts are being added to the language which should vastly improve the compile error to something like `Error: std::bitset<3> does not model Comparable` – Ayjay Oct 12 '19 at 07:21
  • Thank you for clarifying. Can I ask which compiler are you using? – W.R. Oct 12 '19 at 07:42
  • Visual Studio 2019 – Ayjay Oct 13 '19 at 22:21