简体   繁体   English

对具有不可复制值的stl容器使用boost序列化时出现编译错误

[英]Compilation error in using boost serialization for stl containers with non-copyable values

If I have a non-copyable class and use this class as a value type of a stl container that I wanted to serialize it using boost serialize I get a compile error which indicates that I had wanted to use a deleted function. 如果我有一个不可复制的类并将该类用作要使用boost serialize对其进行序列化的stl容器的值类型,则会收到一个编译错误,表明我想使用已删除的函数。 A simple code that causes the error is like this: 导致错误的简单代码如下:

#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

#include <fstream>
#include <iostream>
#include <unordered_map>

using namespace std;

class Foo
{                                                                                                                                                                                
public:
  string s;

  Foo()
  {}

  Foo(string s):
    s(s)
  {}


  Foo(const Foo& other) = delete;
  Foo &operator=(const Foo &other) = delete;

  Foo(Foo &&other) noexcept = default;
  Foo &operator=(Foo &&other) noexcept = default;



  template <typename Archive>
  void save(Archive &ar, const unsigned int version) const
  {
    ar & this->s;
  }

  template <typename Archive>
  void load(Archive &ar, const unsigned int version)
  {
    ar & this->s;
  }

  BOOST_SERIALIZATION_SPLIT_MEMBER()

  friend class boost::serialization::access;
};

int main(int argc, char *argv[])
{
  vector<pair<const uint8_t, Foo>> bar;

  const char* text_file_name = "/tmp/test-fixed-multibit.txt";
  {
    std::ofstream ofs(text_file_name);
    boost::archive::text_oarchive ar(ofs);
    ar & bar;
  }

  {
    vector<pair<const uint8_t, Foo>> bar1;

    std::ifstream ifs(text_file_name);
    boost::archive::text_iarchive ar(ifs);

    ar & bar1;
  }
  return 0;
}

Which it gives me an error like this: 它给我这样的错误:

/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(std::pair<_T1, _T2>&&) [with _T1 = const unsigned char; _T2 = Foo]’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:64:0,
                 from /usr/include/c++/4.8/vector:60,
                 from /usr/local/include/boost/serialization/vector.hpp:20,
                 from foo.cc:3:
/usr/include/c++/4.8/bits/stl_pair.h:128:17: note: ‘constexpr std::pair<_T1, _T2>::pair(std::pair<_T1, _T2>&&) [with _T1 = const unsigned char; _T2 = Foo]’ is implicitly deleted because the default definition would be ill-formed:
       constexpr pair(pair&&) = default;
                 ^
/usr/include/c++/4.8/bits/stl_pair.h:128:17: error: use of deleted function ‘Foo::Foo(const Foo&)’
foo.cc:28:3: error: declared here
   Foo(const Foo& other) = delete;

I deleted some parts of the error, but they were like lines we have copied here. 我删除了错误的某些部分,但它们就像我们在此处复制的行一样。 You can check the correctness of the code by replacing Foo with another type like string . 您可以通过将Foo替换为string等其他类型来检查代码的正确性。

Do I have a mistake about using boost or is this a misbehavior of boost serialize? 我在使用boost时是否有错误,或者这是boost序列化的不当行为?

I used c++11 with g++-4.8 and my boost version is 1-60.0 compiled from source. 我将c ++ 11与g ++-4.8一起使用,我的boost版本是从源代码编译的1-60.0。

Edit: 编辑:

As @sehe stated in his answer using g++-5.x can solve the compile error. 正如@sehe在使用g ++-5.x的答案中所述,可以解决编译错误。 But it is true just for std::vector and using other containers like std::unordered_map causes the same compile error even with g++-5.x. 但是,仅对于std::vector并使用其他容器(例如std::unordered_map ,即使对于g ++-5.x,也会导致相同的编译错误,这是事实。

The problems seems to be that std::string is not noexcept move-assignable: 问题似乎是std::string不是noexcept -assignable:

  // PR 58265, this should be noexcept.
  // _GLIBCXX_RESOLVE_LIB_DEFECTS
  // 2063. Contradictory requirements for string move assignment

(that's from line 584 in my basic_string.h) (来自我basic_string.h中的584行)

Indeed replacing std::string with int make everything work fine: 确实用int替换std::string使一切正常:

Live On Coliru 生活在Coliru

#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

#include <fstream>
#include <iostream>
#include <unordered_map>

struct Foo {
    int s;

    Foo(int s = {}) : s(s) {}

    Foo(const Foo &other) = delete;
    Foo &operator=(const Foo &other) = delete;

    Foo(Foo &&other) noexcept = default;
    Foo &operator=(Foo &&other) noexcept = default;

    template <typename Archive> void save(Archive &ar, const unsigned int version) const { ar & this->s; }

    template <typename Archive> void load(Archive &ar, const unsigned int version) { ar & this->s; }

    BOOST_SERIALIZATION_SPLIT_MEMBER()

    friend class boost::serialization::access;
};

int main(int argc, char *argv[]) {
    std::vector<std::pair<const uint8_t, Foo> > bar;

    const char *text_file_name = "test-fixed-multibit.txt";
    {
        std::ofstream ofs(text_file_name);
        boost::archive::text_oarchive ar(ofs);
        ar & bar;
    }

    {
        std::vector<std::pair<const uint8_t, Foo> > bar1;

        std::ifstream ifs(text_file_name);
        boost::archive::text_iarchive ar(ifs);

        ar & bar1;
    }
}

It seems a bug in boost code, I reported this in boost bug tracker. 在Boost代码中似乎存在错误,我在boost bug跟踪器中报告了错误。 But for a fast solution you could change one line in file boost/serialization/archive_input_unordered_map.hpp line 43 ( s.insert(t.reference()); ) must be replaced with: 但是为了快速解决方案,您可以在文件boost/serialization/archive_input_unordered_map.hpp第43行中更改一行( s.insert(t.reference()); )必须替换为:

  s.emplace(std::piecewise_construct,
            std::forward_as_tuple(std::move(t.reference().first)),
            std::forward_as_tuple(std::move(t.reference().second)));

This is for boost-1.60 and you must find the line in other versions, and it just corrects unordered_map insertion. 这是针对boost-1.60的,您必须在其他版本中找到该行,并且它仅会纠正unordered_map插入。 May be general solution possible for that but currently this patch solved my problem. 可能是通用的解决方案,但当前此补丁解决了我的问题。

Update: 更新:

As in the bug have reported, this bug has fixed in boost-1.61. 错误所报告,此错误已在boost-1.61中修复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM