我试图在unix机器上编译一些(迄今为止)的windows代码但是在以下方法中出现了一些错误:
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!
}
}
错误如下所示:
test.cpp:在成员函数'void EDIN :: World :: Save(const char *)'中: test.cpp:122:12:错误:'operator&lt;&lt;'不匹配(操作数类型是 'boost :: archive :: text_oarchive'和'EDIN :: World *') oa&lt;&lt;这个&lt;&lt; cellSequence&lt;&lt;报告; //第590行:错误! ^ 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: 注意:存档&amp; 升压::归档::详细:: interface_oarchive ::运营商LT;≤(T&安培) [与T = EDIN ::世界*; Archive = boost :: archive :: text_oarchive] 存档&amp;运营商&lt;(&lt;(T&amp; t){ ^ /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/interface_oarchive.hpp:62:15: 注意:没有已知的从'EDIN :: World *'到参数1的转换 “EDIN ::全球*安培;”
我使用boost 1.55.0(与我在Visual Studio上编译时相同)。谁能发现我在这里做错了什么?
以下是来自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;
}
compiles fine here使用GCC 4.8.1和Boost 1.55.0。我正在使用GCC 4.9.0并提升1.55.0。
编辑:我发现了一个似乎有效的黑客攻击:
问题似乎是G ++ 4.9不想将World::this
从World*
投射到World*&
。用以下内容替换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;
}
GCC 4.8.1和GCC 4.9之间的行为似乎存在差异,导致后者无法编译,除非我创建this
指针的副本。如果有人可以指出为什么会发生这种情况,以及它是否是一个可以理解的行为中的错误或预期的变化!
答案 0 :(得分:3)
您没有提供所有必要的信息。
这是一个基于您/做/显示的示例代码
的自包含示例如您所见,它运行良好。我认为唯一可能导致问题的重要编辑是:
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!
}
麻烦在于,const&
按值或返回 ,因为t
指针在此上下文中也是const。但是,ar <<
需要非const引用** [1] **,所以它不应该编译。
MSVC可能接受它的原因可能是因为MSVC有一个(邪恶的)非标准扩展,延长了临时工作的生命周期,当绑定到非const引用时。
我的演示应用程序显示了序列化和反序列化:
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");
}
您可以验证world.save
和world2.save
最终是否与您自己相同(同样在 coliru )。
完整的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] 由于技术原因不明确,超出了此范围
答案 1 :(得分:0)
除非有人提出真正的解决方案,否则这不是一个黑客的答案。问题似乎是G ++ 4.9不想将World::this
从World*
投射到World*&
。用以下内容替换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;
}
GCC 4.8.1和GCC 4.9之间的行为似乎存在差异,导致后者无法编译,除非我创建this
指针的副本。如果有人可以指出为什么会发生这种情况,以及它是否是一个可以理解的行为中的错误或预期的变化!