Search code examples
c++boostqt4boost-multi-index

boost::multi_index_container with random_acces and hashed_unique


I'am trying to create container with both index and key access with unique keys: so here is my code:

#include <QString>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/mem_fun.hpp>

class MyClass{
public:
    MyClass( const QString& name ): mName( name ){}
    QString name    ( ) const { return mName; }
    void    setName ( const QString& name ) { mName = name ;}
private:
    QString mName;
};


using namespace boost::multi_index;
typedef multi_index_container<
    MyClass,
    indexed_by<
        random_access<tag<struct RandomIndex>>,
        hashed_unique<
            tag<struct NameIndex>,
            const_mem_fun<MyClass, QString, &MyClass::name>
        >
    >
> Table;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Table table;
    for (MyClass v : { "first", "second", "third" }){
        table.push_back(v);
    }

    return a.exec();
}

When I try to compile it I have an error boost_1_55_0\boost\functional\hash\extensions.hpp:269: error: C2664: 'size_t boost::hash_value(std::type_index)' : cannot convert argument 1 from 'const QString' to 'std::type_index' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

As I can see boost doesn't know nothing abt Qt class QString, but I am fail to find how to fix this problem. Can someone explain how to fix my code?


Solution

  • You need to tell Boost how to hash QString.

    Simplest way would seem:

    namespace boost {
        template <> struct hash<QString> {
            size_t operator()(QString const& v) const {
                return qHash(v);
            }
        };
    }
    

    Complete working example:

    #include <QtCore/QString>
    #include <QtCore/QHash>
    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/hashed_index.hpp>
    #include <boost/multi_index/random_access_index.hpp>
    #include <boost/multi_index/mem_fun.hpp>
    
    class MyClass{
    public:
        MyClass( const QString& name ): mName( name ){}
        QString name    ( ) const { return mName; }
        void    setName ( const QString& name ) { mName = name ;}
    private:
        QString mName;
    };
    
    namespace boost {
        template <> struct hash<QString> {
            size_t operator()(QString const& v) const {
                return qHash(v);
            }
        };
    }
    
    
    using namespace boost::multi_index;
    typedef multi_index_container<
        MyClass,
        indexed_by<
            random_access<tag<struct RandomIndex>>,
            hashed_unique<
                tag<struct NameIndex>,
                const_mem_fun<MyClass, QString, &MyClass::name>
            >
        >
    > Table;
    
    #include <QtGui/QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Table table;
        for (QString v : { "first", "second", "third" }){
            table.push_back(MyClass(v));
        }
    
        return a.exec();
    }