[英]error: no match for 'operator<<' using boost::serialisation
I am trying to get some (hitherto) windows code to compile on a unix machine but am getting some errors at the following method: 我正在尝试获取一些(迄今为止)Windows代码以在UNIX机器上进行编译,但是在以下方法中出现了一些错误:
namespace EDIN {
void World::Save(char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << this << cellSequence << report; // line 590: error!
}
}
The error looks like this: 错误看起来像这样:
test.cpp: In member function 'void EDIN::World::Save(const char*)': test.cpp:122:12: error: no match for 'operator<<' (operand types are 'boost::archive::text_oarchive' and 'EDIN::World*') oa << this << cellSequence << report;
test.cpp:在成员函数'void EDIN :: World :: Save(const char *)'中:test.cpp:122:12:错误:'operator <<'不匹配(操作数类型为'boost :: archive :: text_oarchive'和'EDIN :: World *')oa <<此<< cellSequence <<报告; // line 590: error!
//第590行:错误! ^ test.cpp:122:12: note: candidate is: In file included from /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/common_oarchive.hpp:22:0, from /home/armanschwarz/lib/boost_1_55_0/boost/archive/basic_text_oarchive.hpp:32, from /home/armanschwarz/lib/boost_1_55_0/boost/archive/text_oarchive.hpp:31, from test.cpp:1: /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/interface_oarchive.hpp:62:15: note: Archive& boost::archive::detail::interface_oarchive::operator<<(T&) [with T = EDIN::World*;
^ test.cpp:122:12:注意:候选者是:在/home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/common_oarchive.hpp:22:0中包含的文件中,来自/ home / armanschwarz / lib / boost_1_55_0 /boost/archive/basic_text_oarchive.hpp:32,来自/home/armanschwarz/lib/boost_1_55_0/boost/archive/text_oarchive.hpp:31,来自test.cpp:1:/ home / armanschwarz / lib / boost_1_55_0 / boost / archive /detail/interface_oarchive.hpp:62:15:注意:Archive&boost :: archive :: detail :: interface_oarchive :: operator <<(T&)[with T = EDIN :: World *; Archive = boost::archive::text_oarchive] Archive & operator<<(T & t){ ^ /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/interface_oarchive.hpp:62:15: note: no known conversion for argument 1 from 'EDIN::World*' to 'EDIN::World*&'
存档= boost :: archive :: text_oarchive]存档和运算符<<(T&t){^ /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/interface_oarchive.hpp:62:15:注意:没有已知的转换对于参数1从'EDIN :: World *'到'EDIN :: World *&'
I'm using boost 1.55.0 (same as when I used to compile this on Visual Studio). 我正在使用boost 1.55.0(与我以前在Visual Studio上进行编译时相同)。 Can anyone spot what I'm doing wrong here?
有人可以在这里发现我在做什么错吗?
Here is a self-contained example from sehe: 这是sehe的一个独立示例:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/valarray.hpp>
#include <chrono>
namespace EDIN
{
struct Region
{
int id;
Region(int id = 42) : id(id) {}
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int file_version)
{
ar & id;
}
};
struct Scheme
{
std::string GetSchemeType() const { return "scheme_type_42"; }
};
class World
{
// dummy members to make it compile
// will be different things of course
int mass, epoch;
std::chrono::system_clock::time_point _start;
std::string report;
public:
std::vector<int> cellSequence; // for demo, public
World(std::string&, EDIN::Region&, unsigned int&, const std::chrono::system_clock::time_point&)
: mass(99), epoch(88), _start(std::chrono::system_clock::now()), report("Report101")
{
// TODO!
}
Region Bounds() const { return Region(); }
int Epoch() const { return epoch; }
EDIN::Scheme Scheme() const { return EDIN::Scheme(); }
std::chrono::system_clock::time_point StartingWallTime() const {
return _start;
}
World()
: mass(99), epoch(88), _start(std::chrono::system_clock::now()), report("Report101")
{
}
void Save(char const filename[]);
static World* Load(char const filename[]);
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int file_version)
{
ar & mass & epoch;
}
};
}
namespace boost
{
namespace serialization
{
template<class Archive>
inline void save_construct_data(Archive & ar, EDIN::World const * t, unsigned const int file_version)
{
time_t const totalRunningTime = std::chrono::duration_cast<std::chrono::duration<time_t, std::milli>>(
std::chrono::system_clock::now() - t->StartingWallTime()).count();
EDIN::Region const bounds = t->Bounds();
time_t const epoch = t->Epoch();
std::string tmp = t->Scheme().GetSchemeType();
ar
<< bounds
<< epoch
<< totalRunningTime
<< tmp;
}
template<class Archive>
inline void load_construct_data(Archive & ar, EDIN::World * t, const unsigned int file_version)
{
EDIN::Region bounds;
unsigned epoch;
time_t totalRunningTime;
std::string schemeType;
ar >>
bounds >>
epoch >>
totalRunningTime >>
schemeType;
std::chrono::system_clock::time_point const startingWallTime =
std::chrono::system_clock::now() - std::chrono::duration<time_t, std::milli>(totalRunningTime);
::new(t) EDIN::World(schemeType,bounds,epoch,startingWallTime);
}
}
}
#include <fstream>
namespace EDIN {
void World::Save(char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << this << cellSequence << report; // line 590: error!
}
World* World::Load(char const filename[])
{
World *world = 0;
std::ifstream ifs("world.save");
boost::archive::text_iarchive ia(ifs);
ia >> world;
ia >> world->cellSequence >> world->report;
return world;
}
}
int main()
{
EDIN::World world;
world.cellSequence.push_back(12345);
world.cellSequence.push_back(-6767);
world.Save("world.save");
EDIN::World* restored = EDIN::World::Load("world.save");
restored->Save("world2.save");
delete restored;
}
It compiles fine here using GCC 4.8.1 and Boost 1.55.0. 在这里使用GCC 4.8.1和Boost 1.55.0可以很好地进行编译。 I am using GCC 4.9.0 and boost 1.55.0.
我正在使用GCC 4.9.0和Boost 1.55.0。
EDIT: I have found a hack that seems to work: 编辑:我发现一种黑客似乎有效:
The problem seems to be that G++ 4.9 doesn't want to cast World::this
from World*
to World*&
. 问题似乎是G ++ 4.9不想将
World::this
从World*
为World*&
。 Replacing the World::Save
method with the following resolves the problem: 用以下替换
World::Save
方法可以解决此问题:
void World::Save(char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
World* thisCopy = this;
oa << thisCopy << cellSequence << report;
}
There seems to be a difference in behaviour between GCC 4.8.1 and GCC 4.9 that causes the latter not to compile unless I create copy of the this
pointer. 在GCC 4.8.1和GCC 4.9之间,似乎在行为上存在差异,这导致后者无法编译,除非我创建了
this
指针的副本。 If someone could point out why this is happening and whether or not it's a bug or intended change in behaviour that would be appreciated! 如果有人可以指出为什么会这样,以及是否是错误或行为上的预期变化,我们将不胜感激!
You are not giving all the information necessary. 您没有提供所有必要的信息。
Here's a self-contained example based on the sample code you /did/ show 这是一个基于您/ did /显示的示例代码的独立示例
As you can see, it runs fine. 如您所见,它运行良好。 The only significant edits I think that may be causing trouble are these:
我认为可能引起麻烦的唯一重要编辑是:
std::string tmp = t->Scheme().GetSchemeType();
ar
<< bounds
<< epoch
<< totalRunningTime
<< tmp;
// and the following (use of this as mutable reference, which some versions of GCC erronously accepted)
void SaveWorld(World* world, char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << world << world->cellSequence << world->report; // line 590: error!
}
The trouble is that returns either by value, or by const&
, because the t
pointer is also const in this context. 麻烦的是要么按值返回, 要么按
const&
,因为在这种情况下t
指针也是const。 However, ar <<
requires a non-const references** [1] **, so it should not compile. 但是,
ar <<
需要非常量引用** [1] **,因此不应编译。
The reason MSVC might have accepted it, nonetheless, could be because MSVC has an (evil) non-standard extension that extends lifetimes of temporaries, when bound to a non-const reference . 尽管如此,MSVC可能接受它的原因可能是因为MSVC具有一个(邪恶的)非标准扩展名,该扩展名在绑定到非const引用时可以延长临时对象的生存期 。
My demo app shows serialization and deserialization in action: 我的演示应用程序显示了实际的序列化和反序列化:
int main()
{
using namespace EDIN;
std::unique_ptr<World> world(new World);
world->cellSequence.push_back(12345);
world->cellSequence.push_back(-6767);
SaveWorld(world.get(), "world.save");
world.reset(LoadWorld("world.save"));
SaveWorld(world.get(), "world2.save");
}
And you can verify that world.save
and world2.save
end up being identical for yourself (also on coliru ). 并且您可以验证
world.save
和world2.save
最终对您自己是相同的(也在coliru上 )。
Full SSCCE code for reference: 完整的SSCCE代码供参考:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/valarray.hpp>
#include <chrono>
#include <memory>
namespace EDIN
{
struct Region
{
int id;
Region(int id = 42) : id(id) {}
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int file_version)
{
ar & id;
}
};
struct Scheme
{
std::string GetSchemeType() const { return "scheme_type_42"; }
};
class World
{
// dummy members to make it compile
// will be different things of course
int mass, epoch;
std::chrono::system_clock::time_point _start;
std::string report;
public:
std::vector<int> cellSequence; // for demo, public
World(std::string&, EDIN::Region&, unsigned int&, const std::chrono::system_clock::time_point&)
: mass(99), epoch(88), _start(std::chrono::system_clock::now()), report("Report101")
{
// TODO!
}
Region Bounds() const { return Region(); }
int Epoch() const { return epoch; }
EDIN::Scheme Scheme() const { return EDIN::Scheme(); }
std::chrono::system_clock::time_point StartingWallTime() const {
return _start;
}
World()
: mass(99), epoch(88), _start(std::chrono::system_clock::now()), report("Report101")
{
}
friend void SaveWorld(World* world, char const filename[]);
friend World* LoadWorld(char const filename[]);
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int file_version)
{
ar & mass & epoch;
}
};
}
namespace boost
{
namespace serialization
{
template<class Archive>
inline void save_construct_data(Archive & ar, EDIN::World const * t, unsigned const int file_version)
{
time_t const totalRunningTime = std::chrono::duration_cast<std::chrono::duration<time_t, std::milli>>(
std::chrono::system_clock::now() - t->StartingWallTime()).count();
EDIN::Region const bounds = t->Bounds();
time_t const epoch = t->Epoch();
std::string tmp = t->Scheme().GetSchemeType();
ar
<< bounds
<< epoch
<< totalRunningTime
<< tmp;
}
template<class Archive>
inline void load_construct_data(Archive & ar, EDIN::World * t, const unsigned int file_version)
{
EDIN::Region bounds;
unsigned epoch;
time_t totalRunningTime;
std::string schemeType;
ar >>
bounds >>
epoch >>
totalRunningTime >>
schemeType;
std::chrono::system_clock::time_point const startingWallTime =
std::chrono::system_clock::now() - std::chrono::duration<time_t, std::milli>(totalRunningTime);
::new(t) EDIN::World(schemeType,bounds,epoch,startingWallTime);
}
}
}
#include <fstream>
namespace EDIN {
void SaveWorld(World* world, char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << world << world->cellSequence << world->report; // line 590: error!
}
World* LoadWorld(char const filename[])
{
World *world = 0;
std::ifstream ifs("world.save");
boost::archive::text_iarchive ia(ifs);
ia >> world;
ia >> world->cellSequence >> world->report;
return world;
}
}
int main()
{
using namespace EDIN;
std::unique_ptr<World> world(new World);
world->cellSequence.push_back(12345);
world->cellSequence.push_back(-6767);
SaveWorld(world.get(), "world.save");
world.reset(LoadWorld("world.save"));
SaveWorld(world.get(), "world2.save");
}
[1] For obscure technical reasons, beyond the scope here [1]出于晦涩的技术原因,超出了此处的范围
This is not so much an answer as a hack until someone proposes a real solution. 除非有人提出真正的解决方案,否则这不是一个解决之道。 The problem seems to be that G++ 4.9 doesn't want to cast
World::this
from World*
to World*&
. 问题似乎是G ++ 4.9不想将
World::this
从World*
为World*&
。 Replacing the World::Save
method with the following resolves the problem: 用以下替换
World::Save
方法可以解决此问题:
void World::Save(char const filename[])
{
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
World* thisCopy = this;
oa << thisCopy << cellSequence << report;
}
There seems to be a difference in behaviour between GCC 4.8.1 and GCC 4.9 that causes the latter not to compile unless I create copy of the this
pointer. 在GCC 4.8.1和GCC 4.9之间,似乎在行为上存在差异,这导致后者无法编译,除非我创建了
this
指针的副本。 If someone could point out why this is happening and whether or not it's a bug or intended change in behavior that would be appreciated! 如果有人可以指出为什么会这样,以及是否是错误或行为上的预期变化,我们将不胜感激!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.