0
\$\begingroup\$

I'm making a multiplayer game, the Server stores it's game world state as various std::unordered_map in a class called ServerWorldState.

The server is composed by a single class called Game, which contains ServerWorldState.

Currently I'm trying to make Save() and Load() functions, which for now will be in the Game class. These functions are supposed to save certain data from the maps within ServerWorldState into a binary archive, for this purpose, I'm using Cereal library for serialization and the standard file IO streams.

Cereal requires a serialize method to be present in a class, in order for members to be specified for serialization:

ServerWorldState.h

class ServerWorldState : public World
{
private:
    std::unordered_map<int, ServerProp> props;
public:
    template<class Archive>
    void serialize(Archive& archive);

};

ServerWorldState.cpp

template<class Archive>
void ServerWorldState::serialize(Archive& archive)
{
    archive(props); //Serialize things by passing them to the archive
}

The ServerProp class actually has another serialize method within itself. I'm unsure if this is correct for specifying with further depth what object members should get serialized.

Save function from Game (load works very similar and has same problem, but since I haven't finished it's design I'm only showing save):

Game.h

class Game
{
private:
    std::shared_ptr<ServerWorldState> currentWorld;
public:
    bool Save();
};

Game.cpp

bool Game::Save()
{
    std::ofstream outfile("level.dat", std::ios::binary | std::ios::out);
    if (!outfile) {
        std::cout << "SERVER_WORLD_STATE::SAVE: Could not open world.dat file for saving!" << std::endl;
        return false;
    }

    {
        cereal::PortableBinaryOutputArchive oarchive(outfile); //Create an output archive

        oarchive(currentWorld); //Write data to the archive

    } //Archive goes out of scope, ensuring all contents are flushed

    outfile.close();

    return true;
}

In essence I want to serialize/deserialize and binary save/load the std::unordered_map in ServerWorldState, but I get this link error:

Error LNK2019 unresolved external symbol "public: void __cdecl ServerWorldState::serialize(class cereal::PortableBinaryOutputArchive &)" (??$serialize@VPortableBinaryOutputArchive@cereal@@@ServerWorldState@@QEAAXAEAVPortableBinaryOutputArchive@cereal@@@Z) referenced in function "public: static void __cdecl cereal::access::member_serialize(class cereal::PortableBinaryOutputArchive &,class ServerWorldState &)" (??$member_serialize@VPortableBinaryOutputArchive@cereal@@VServerWorldState@@@access@cereal@@SAXAEAVPortableBinaryOutputArchive@1@AEAVServerWorldState@@@Z) - Game.obj line 1

I would asume this would show if the serialize method wasn't defined, but it is. I also thought I might be missing some inclusion, but I seem to have all in order.

\$\endgroup\$
  • 1
    \$\begingroup\$ The linker can't see template definitions in source files. \$\endgroup\$ – Tyyppi_77 May 25 at 4:16
  • \$\begingroup\$ indeed it may be because of the deported definition, building ServerWorldState.cpp will be fine but not Game.cpp and ServerWorldState.cpp together. put the def inline in the .h to check? \$\endgroup\$ – v.oddou May 25 at 8:41
  • \$\begingroup\$ Yes, having the method definition in the .h actually fixes this. Not entirely sure how I feel about the actual definition being in the .h though. I actually read it may be faster, but I'm used to always having definitions in .cpp \$\endgroup\$ – Mithrandir May 25 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.