Смешивание Qt с STL и Boost - есть ли мосты, чтобы сделать это легко? - PullRequest
15 голосов
/ 11 мая 2009

Есть ли какие-нибудь мосты, чтобы сделать смешивание Qt с STL и Boost как можно более простым и легким?

Это продолжение Смешивание Qt и Boost , где не было дано конкретных ответов, как этого добиться.

Ответы [ 3 ]

37 голосов
/ 13 мая 2009

Какие мосты вам нужны?

Вы можете использовать все классы контейнеров Qt с алгоритмами std. Большую часть времени я предпочитаю классы контейнера Qt, потому что я уверен, что они используют идиому копирования при записи (операция с постоянным временем). Функция foret в Qt создает копию контейнера, поэтому приятно, что вы точно знаете, что это операция с постоянным временем.

Если механизм слота сигналов Qt слишком медленный, вы можете переключиться на альтернативу наддува. Самое замечательное в сигнале / слоте Qt - это соединение сигнал / слот между двумя потоками.

QtConcurrent отлично работает с BOOST.Lambda


Для «общих» дочерних и родительских отношений я использую эту вспомогательную функцию.

template <class Object>
static boost::shared_ptr<Object> makeSharedObject()
{
    using namespace boost;
    using namespace boost::lambda;
    return boost::shared_ptr<Object>( 
        new Object(),
        bind( &Object::deleteLater, _1 ) );
}

Контейнеры Qt не поддерживаются Boost.serialize, вам придется самостоятельно писать функции сериализации. Я бы хотел мост между потоковыми классами Qt и Boost.archive.

Вот мой шаблон сериализации QList, с которым вы можете разобраться ...

///\file document is based on "boost/serialization/list.hpp"

namespace boost { 
    namespace serialization {

        //---------------------------------------------------------------------------
        /// Saves a QList object to a collection 
        template<class Archive, class U >
        inline void save(Archive &ar, const QList< U > &t, const uint /* file_version */ )
        {
            boost::serialization::stl::save_collection< Archive, QList<U> >(ar, t);
        }

        //---------------------------------------------------------------------------
        /// Loads a QList object from a collection 
        template<class Archive, class U>
        inline void load(Archive &ar, QList<U > &t, const uint /* file_version */ )
        {
                boost::serialization::stl::load_collection< 
                    Archive, 
                    QList<U>, 
                    boost::serialization::stl::archive_input_seq<Archive, QList<U> >,
                    boost::serialization::stl::no_reserve_imp< QList<U> > >(ar, t);
        }

        //---------------------------------------------------------------------------
        /// split non-intrusive serialization function member into separate
        /// non intrusive save/load member functions
        template<class Archive, class U >
        inline void serialize(Archive &ar, QList<U> &t, const uint file_version )
        {
            boost::serialization::split_free( ar, t, file_version);
        }

    } // namespace serialization
} // namespace boost

BOOST_SERIALIZATION_COLLECTION_TRAITS(QList)

Если вы хотите, чтобы Boost.Bind обрабатывал QPointer как обычный указатель (например, shared_ptr):

namespace boost {

    template<typename T> T * get_pointer(QPointer<T> const& qPointer)
    {
        return qPointer;
    }
}

Использование QIODevice, где требуется std::stream

namespace boost {
    namespace iostreams {

        class IoDeviceSource 
        {
        public:
            typedef char char_type;
            typedef source_tag category;

            explicit IoDeviceSource(QIODevice& source) 
                : m_source(source) 
            {
            }

            std::streamsize read(char* buffer, std::streamsize n)
            {
                return return m_source.read(buffer, n);
            }   
        private:
            QIODevice& m_source;
        };

        class IoDeviceSink {

        public:
            typedef char char_type;
            typedef sink_tag category;

            explicit IoDeviceSink(QIODevice& sink)
                : m_sink(sink)
            {
            }

            std::streamsize write(const char_type* buffer, std::streamsize n) 
            {
                return m_sink.write(buffer, n);
            }

        private:
            QIODevice &m_sink;
        };

        class IoDeviceDevice {

        public:
            typedef char char_type;
            typedef seekable_device_tag category;

            explicit IoDeviceDevice(QIODevice& device)
                :m_device(device) {
            }

            std::streamsize write(const char_type *buffer, std::streamsize n)
            {
                return m_device.write(buffer, n);
            }

            std::streamsize read(char* buffer, std::streamsize n)
            {
                return m_device.read(buffer, n);
            }

            stream_offset seek(stream_offset off, std::ios_base::seekdir way)
            {
                using namespace std;
                stream_offset next(0);

                if(way==ios_base::beg)
                {
                    next = m_device.pos();
                } 
                else if(way==ios_base::cur)
                {
                    next = m_device.pos() + offset;
                } 
                else if(way==ios_base::end)
                {
                    next = m_device.size() -1 + offset;
                }
                else
                {
                    throw ios_base::failure("bad seek direction");
                }

                if( !m_device.seek(next) )
                {
                    throw ios_base::failure("bad seek offset");
                }
                return m_device.pos();
            }

        private:    
            QIODevice &m_device;
        };
    }
}

Пример * +1031 *

#include <iostream>
#include <QFile>
#include <boost/iostreams/stream.hpp>
#include "iodevicestream.h"

int main(int argc, char *argv[])
{
    namespace io = boost::iostreams;

    QVector<int> data;

    QFile fl("temp.bin");
    fl.open(QIODevice::ReadWrite);
    io::stream<io::IoDeviceDevice> inoutput( fl );  

    std::copy(data.begin(), data.end(), std::ostream_iterator<int>(inoutput, "\n"));
    inoutput.flush();
    inoutput.seekg(0, std::ios_base::beg);
    std::cout << inoutput;
    return 0;
}
3 голосов
/ 11 мая 2009

В чем именно проблема?
Вы можете игнорировать все классы коллекции Qt, если хотите, и использовать эквиваленты STL.
Точно так же вы можете использовать кросс-платформенные файловые / сетевые библиотеки Boost.

Основной причиной использования собственной Qt, вероятно, является то, что повышение не обязательно так широко доступно, особенно на мобильных устройствах. Некоторые библиотеки Boost немного сложнее в использовании, чем Qt для простых задач.

2 голосов
/ 11 мая 2009

В общем, вы будете чувствовать себя лучше при использовании QT, если будете придерживаться классов QT Collection, а не нас STL. В Qt, STL или Boost по сути нет ничего, что мешало бы использовать их тогда внутри друг друга.

Вы должны быть осторожны, когда используете умные указатели. QT имеет отношения родитель / потомок, которые могут позаботиться об уничтожении объектов, освобождение объектов, когда они находятся под контролем Qt, приведет к краху.

...