将 Qt 与 STL 和 Boost 混合 - 有没有任何桥梁可以使它变得简单?

发布于 2024-07-19 03:58:29 字数 156 浏览 4 评论 0原文

是否有任何桥梁可以使 Qt 与 STL 和 Boost 的混合尽可能无缝且简单?

这是混合 Qt 和 Boost 的后续内容,其中没有给出如何完成此操作的具体答案。

Are there any bridges to make mixing Qt with STL and Boost as seamless and easy as possible?

This is a followup to Mixing Qt and Boost, where no specific answers how to accomplish this were given.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

软的没边 2024-07-26 03:58:29

你需要什么桥梁?

您可以将所有 Qt 容器类与 std 算法一起使用。
大多数时候我更喜欢 Qt 容器类,因为我确信它们使用写时复制习惯用法(恒定时间操作)。 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 ) );
}

Boost.serialize 不支持 Qt 容器,您必须自己编写序列化函数。
我希望在 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 作为普通指针(如共享指针)处理:

namespace boost {

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

使用 QIODevice where 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;
}

What bridges do you need?

You can use all the Qt container classes with std algorithms.
Most of the time I prefer the Qt container classes because I'm sure they use the copy-on-write idiom (constant time operation). Qt's foreach function creates a copy of the container so its nice that you know for sure it is a constant time operation.

If the Qt signal slot mechanism is to slow you can switch to the boost alternative.
The great thing about Qt signal/slot is the signal/slot connection between two threads.

QtConcurrent works great with BOOST.Lambda


For "shared" child-parent relationship I use this helper function.

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 containers are not supported by Boost.serialize, you'll have to write the serialize functions yourself.
I would love a bridge between the Qt streaming classes and Boost.archive.

Here is my QList serialization template you can figure out the rest of them ...

///\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)

If you want Boost.Bind to handle QPointer as a normal pointer (like shared_ptr):

namespace boost {

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

Using QIODevice where a std::stream is needed

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;
        };
    }
}

Example

#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;
}
眼角的笑意。 2024-07-26 03:58:29

到底是什么问题?
如果您愿意,可以忽略所有 Qt 集合类并使用 STL 等效项。
同样,您可以使用 Boost 的跨平台文件/网络库。

使用 Qt 自己的主要原因可能是 boost 不一定广泛可用,尤其是在移动设备上。 对于简单任务,Boost 的一些库使用起来比 Qt 的库稍微复杂一些。

What exactly is the problem?
You can ignore all the Qt collection classes if you want and use STL equivalents.
Similarly you can use Boost's cross platform file/network libs.

The main reason to use Qt's own is probably that boost isn't necessarily that widely available, especially on mobile devices. Some of Boost's libs are a little more complicated to use than the Qt ones for simple tasks.

清君侧 2024-07-26 03:58:29

一般来说,如果您坚持使用 QT Collection 类而不是我们的 STL,那么在使用 QT 时您会表现得更好。 Qt、STL 或 Boost 本身并不妨碍相互使用 then。

使用智能指针时必须小心,QT 具有父/子关系,可以处理对象的销毁,当对象受 Qt 控制时释放对象将使您崩溃。

In general you are going to fare better when using QT if you stick to the QT Collection classes rather than us STL. There is nothing per se in Qt, STL or Boost that would preclude using then within each other.

You would have to be careful when using smart pointers QT has parent/child relationship that can take care of destruction of objects, deallocating objects when they under control of Qt will make you crash.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文