C++ Boost - 序列化错误 - 将“const B”作为“this”参数传递会丢弃限定符

Posted

技术标签:

【中文标题】C++ Boost - 序列化错误 - 将“const B”作为“this”参数传递会丢弃限定符【英文标题】:C++ Boost - serialization error - passing ‘const B’ as ‘this’ argument discards qualifiers 【发布时间】:2018-08-12 11:46:00 【问题描述】:

我正在尝试使用Boost 序列化一个简单的类。我的班级只包含一个std::vector,如下面的代码所示。我的问题是,当我按照the documentation 进行操作时,我收到了下面描述的错误。我不知道为什么,因为我没有在任何地方定义const。你知道,我做错了什么吗?


我的代码:

#include <fstream>
#include <iostream>
#include <vector>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class B 
    friend class boost::serialization::access;

private:
    std::vector<int>* v;

protected:
    template<class Archive>
    void save(Archive & ar, const unsigned int version)
        ar & this->v->size();
        for(int i = 0; i < this->v->size(); i++) 
            ar & this->v->at(i);
        
    ;

    template<class Archive>
    void load(Archive & ar, const unsigned int version) 
        size_t size;
        int tmp;
        ar & size;

        this->v = new std::vector<int>(size);
        for(int i = 0; i < size; i++) 
            ar & tmp;
            this->v->at(i) = tmp;
        
    

    BOOST_SERIALIZATION_SPLIT_MEMBER()

public:
    B();
    B(std::vector<int>* v);
    void print_vals();
;

B::B() 
    this->v = nullptr;


B::B(std::vector<int>* v) 
    this->v = v;


void B::print_vals() 
    for(auto e : *(this->v)) 
        std::cout << e << std::endl;
    


int main() 
    std::vector<int> v1,2,3;

    B b(&v);

    std::ofstream ofs("b.txt");
    
        boost::archive::text_oarchive oa(ofs);
        oa << b;
        ofs.close();
    


错误

In file included from /usr/include/boost/serialization/extended_type_info_typeid.hpp:37,
                 from /usr/include/boost/archive/detail/oserializer.hpp:39,
                 from /usr/include/boost/archive/detail/interface_oarchive.hpp:23,
                 from /usr/include/boost/archive/detail/common_oarchive.hpp:22,
                 from /usr/include/boost/archive/basic_text_oarchive.hpp:29,
                 from /usr/include/boost/archive/text_oarchive.hpp:31,
                 from /home/martin/CLionProjects/boost_serialization_example/main.cpp:4:
/usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::member_save(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive; T = const B]’:
/usr/include/boost/serialization/split_member.hpp:43:32:   required from ‘static void boost::serialization::detail::member_saver<Archive, T>::invoke(Archive&, const T&, unsigned int) [with Archive = boost::archive::text_oarchive; T = B]’
/usr/include/boost/serialization/split_member.hpp:69:18:   required from ‘void boost::serialization::split_member(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive; T = B]’
/home/martin/CLionProjects/boost_serialization_example/main.cpp:35:5:   required from ‘void B::serialize(Archive&, unsigned int) [with Archive = boost::archive::text_oarchive]’
/usr/include/boost/serialization/access.hpp:116:9:   required from ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive; T = B]’
/usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive; T = B]’
/usr/include/boost/serialization/serialization.hpp:126:14:   [ skipping 4 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/oserializer.hpp:310:22:   required from ‘static void boost::archive::detail::save_non_pointer_type<Archive>::invoke(Archive&, const T&) [with T = B; Archive = boost::archive::text_oarchive]’
/usr/include/boost/archive/detail/oserializer.hpp:534:18:   required from ‘void boost::archive::save(Archive&, T&) [with Archive = boost::archive::text_oarchive; T = const B]’
/usr/include/boost/archive/detail/common_oarchive.hpp:70:22:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&) [with T = const B; Archive = boost::archive::text_oarchive]’
/usr/include/boost/archive/basic_text_oarchive.hpp:83:9:   required from ‘void boost::archive::basic_text_oarchive<Archive>::save_override(T&) [with T = const B; Archive = boost::archive::text_oarchive]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:70:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(const T&) [with T = B; Archive = boost::archive::text_oarchive]’
/home/martin/CLionProjects/boost_serialization_example/main.cpp:107:15:   required from here
/usr/include/boost/serialization/access.hpp:91:9: error: passing ‘const B’ as ‘this’ argument discards qualifiers [-fpermissive]
         t.save(ar, file_version);

编辑 1:

我已经根据答案重写了我的saveload函数,但错误仍然存​​在......

template<class Archive>
void save(Archive & ar, const unsigned int version)
    ar & this->v->size();
    for(int i = 0; i < this->v->size(); i++) 
        ar & (*this->v)[i];
    
;

template<class Archive>
void load(Archive & ar, const unsigned int version) 
    size_t size;
    int tmp;
    ar & size;

    this->v = new std::vector<int>(size);
    for(int i = 0; i < size; i++) 
        ar & tmp;
        (*this->v)[i] = tmp;
    

【问题讨论】:

【参考方案1】:

解决办法:

您的save() 方法需要像这样声明const

void save(Archive & ar, const unsigned int version) const 
...

这将使它编译没有错误。如果您还想要完整的无警告编译,那么还要将save() 内的for 循环修复为这样(将i 的类型从int 更改为size_t):

for (size_t i = 0; i < this->v->size(); i++)

说明:

我不知道为什么,因为我没有在任何地方定义 const。你知道吗, 我做错了什么?

所以问题不在于您没有定义 const,而是您定义的不够。看,当你打电话时

oa << b;

那么boost::archive::text_oarchive 类的运算符&lt;&lt; 的实例化版本具有以下签名:

'Archive &boost::archive::detail::interface_oarchive<Archive>::operator <<<B>(const T &)'

因此,它期望获得const T&amp;。但是,它会满足于常规的T&amp;,因为当期望const 参数时,非const 被接受。但是随后它尝试将其用作 const 无济于事,因为它调用的方法根本没有定义const,因此您值得信赖的编译器足够明智地立即阻止您:)

【讨论】:

谢谢!但我想,只有save 方法应该是const,因为loadconst 使得无法初始化正在加载的对象的属性。 @Eenoku 当然 100%,批准并更正。我思绪飘忽,匆匆写下。我很抱歉。无论如何,现在答案是完整的。希望它有所帮助。

以上是关于C++ Boost - 序列化错误 - 将“const B”作为“this”参数传递会丢弃限定符的主要内容,如果未能解决你的问题,请参考以下文章

C++ | boost库 类的序列化

Boost mpl::list 变体序列化 check_const_loading() 编译错误

如何使用 boost_python 将 C++ 序列化数据公开给 python

如何将序列化方法添加到作为 Windows 数据结构的类成员,以便在 C++ 中与 boost 序列化一起使用

在 boost 中序列化二进制数据失败并出现“无效签名”错误

C++ 网络程序设计:Boost Asio、序列化和 OStream