Есть ли какие-либо мосты, чтобы сделать смешивание Qt с STL и Boost максимально простым и легким?
Это продолжение Смешивание Qt и Boost, где нет конкретных ответов, как выполнить это.
Есть ли какие-либо мосты, чтобы сделать смешивание Qt с STL и Boost максимально простым и легким?
Это продолжение Смешивание Qt и Boost, где нет конкретных ответов, как выполнить это.
Какие мосты вам нужны?
Вы можете использовать все классы контейнеров Qt с помощью std-алгоритмов. Большую часть времени я предпочитаю классы контейнеров Qt, потому что я уверен, что они используют идиому copy-on-write (операция с постоянным временем). Функция Qt foreach создает копию контейнера, поэтому приятно, что вы точно знаете, что это операция с постоянным временем.
Если механизм слота сигнала 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
, где требуется a 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;
};
}
}
Пример
#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;
}
В чем именно проблема?
Вы можете игнорировать все классы коллекции Qt, если хотите, и использовать эквиваленты STL.
Аналогичным образом вы можете использовать файловые/сетевые библиотеки Boost Cross Platform.
Основной причиной использования Qt является, вероятно, то, что повышение не обязательно является широко доступным, особенно на мобильных устройствах. Некоторые из Boost libs немного сложнее в использовании, чем Qt для простых задач.
В общем, вы будете лучше пользоваться при использовании QT, если будете придерживаться классов QT Collection, а не STL. В Qt, STL или Boost нет ничего такого, что исключало бы использование тогда друг в друге.
Вы должны быть осторожны при использовании интеллектуальных указателей. QT имеет отношения родительские/дочерние, которые могут заботиться о уничтожении объектов, освобождая объекты, когда они под контролем Qt заставят вас сбой.