ошибка: нет совпадения с оператором & lt; & lt; используя boost :: serialization

Я пытаюсь получить некоторый (до сих пор) код 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!
}
}

Ошибка выглядит так:

test.cpp: в функции-члене void EDIN :: World :: Save (const char *) ‘:
test.cpp: 122: 12: ошибка: нет совпадения для оператора ‘<<’(Типы операндов
‘Boost :: archive :: text_oarchive’ и ‘EDIN :: World *’)
оа << этот << cellSequence << доклад; // строка 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:
примечание: архив&
повышение :: архив :: подробнее :: interface_oarchive оператор ::<<(Т&)
[с T = EDIN :: World *; Архив = повышение :: архив :: текст_архив] Архив & оператор<<(Т & т) {
^ /home/armanschwarz/lib/boost_1_55_0/boost/archive/detail/interface_oarchive.hpp:62:15:
примечание: нет известного преобразования для аргумента 1 из «EDIN :: World *» в
«Эдин :: World *&»

Я использую 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;
}

Это компилирует нормально здесь используя 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 указатель. Если бы кто-то мог указать, почему это происходит, и является ли это ошибкой или предполагаемым изменением в поведении, это будет оценено!

2

Решение

Вы не даете всю необходимую информацию.

Вот отдельный пример, основанный на примере кода, который вы / сделали / покажете

Как видите, работает нормально. Единственный значительное Я думаю, что правки могут вызывать проблемы:

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 << требует неконстантных ссылок **[1]**, поэтому он не должен компилироваться.

Причина, по которой MSVC мог бы принять это, может быть в том, что MSVC имеет (злое) нестандартное расширение, которое продлевает время жизни временных, когда привязано к неконстантной ссылке.

Мое демонстрационное приложение показывает сериализацию и десериализацию в действии:

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] По неясным техническим причинам, выходящим за рамки здесь

3

Другие решения

Это не столько ответ, сколько взлом, пока кто-то не предложит реальное решение. Проблема в том, что 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

По вопросам рекламы [email protected]