Itolet
Itolet

Reputation: 189

C++ Boost::serialization "no matching function for call" to constructor of the class in my loading function's argument

My actual question is in the bold text below, but here's the context of my problem:

I'm trying out Boost::serialization for saving and restoring a player's state. I read the tutorial at http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/tutorial.html#simplecase, but I'm not sure how

boost::archive::text_iarchive 

works.

I'm working on the assumption that the following lines

boost::archive::text_iarchive inArchive(playerfile);
    inArchive >> target;

will initialize the target according to the playerfile's corresponding textfile?

I'm wrote the following functions with that assumption:

bool SavePlayerState(Player *target)
{
std::string fileName = (target->name) + ".playerfile";
std::ofstream playerfile(fileName);

if(!playerfile.is_open())
{
    s_al_show_native_message_box(display, "SAVE FAILURE", "SAVE FAILURE", fileName + "could not be created/opened.",
                             NULL, ALLEGRO_MESSAGEBOX_ERROR);

    return false;
}

boost::archive::text_oarchive outArchive(playerfile);
outArchive << target;

return true;
}

bool LoadPlayerState(std::string playerName, Player *target)
{
std::string fileName = playerName + ".playerfile";
std::ifstream playerfile(fileName);

if(!playerfile.is_open())
{
    s_al_show_native_message_box(display, "LOAD FAILURE", "LOAD FAILURE", fileName + "could not be found/opened.",
                             NULL, ALLEGRO_MESSAGEBOX_ERROR);

    return false;
}

boost::archive::text_iarchive inArchive(playerfile);
inArchive >> target;

return true;
}

They are called in main() for testing purposes:

int main(int argc, char *argv[])
{
//...

player = new Player(5,5); // There is a Player*player; declared elsewhere
LoadPlayerState("player", player); //Load the file with this name, target is player object
beings.push_back(player);

//The game's operations...

SavePlayerState(player);

delete player;

//...

return 0;
}

SavePlayerState(player); works as I expected, and I find that player.playerfile has been created in my directory. But LoadPlayerState("player", player); gives me the following error:

C:\Development\Libraries\boost\boost\serialization\access.hpp|132|error: no matching function for call to 'Player::Player()'|

I don't know why the constructor should have problems, or why Save works and not Load. I'm not trying to make a new Player object, just shape the existing target Player according to the archive. What do I need to change in order to make this work?

My player class:

#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED

#include "being.h"
#include "extfile.h"

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp>

class Player: public Being
{
friend class boost::serialization::access;
template<class PlayerArchive>
void serialize(PlayerArchive & par, const unsigned int version)
{
    par & boost::serialization::base_object<Being>(*this);

    par & active;
    //par & various things
}

public:
Player(bool savedPlayer);
Player(int spawnXCell, int spawnYCell);
~Player();
//Functions
};

//Prototype to the save and Load state functions mentioned previously are found here.


#endif // PLAYER_H_INCLUDED

Here is my complete build messages log, if it helps:

>||=== Build: Debug in Roguelike (compiler: GNU GCC Compiler) ===|
>C:\Development\Libraries\boost\boost\serialization\access.hpp||In instantiation of 'static void boost::serialization::access::construct(T*) [with T = Player]':|
>C:\Development\Libraries\boost\boost\serialization\serialization.hpp|93|required from 'void boost::serialization::load_construct_data(Archive&, T*, unsigned int) [with Archive = boost::archive::text_iarchive; T = Player]'|
>C:\Development\Libraries\boost\boost\serialization\serialization.hpp|158|required from 'void boost::serialization::load_construct_data_adl(Archive&, T*, unsigned int) [with Archive = boost::archive::text_iarchive; T = Player]'|
>C:\Development\Libraries\boost\boost\archive\detail\iserializer.hpp|341|required from 'void boost::archive::detail::pointer_iserializer::load_object_ptr(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::text_iarchive; T = Player]'|
>C:\Development\Projects\Roguelike\Roguelike\player.cpp|76|required from here|
>C:\Development\Libraries\boost\boost\serialization\access.hpp|132|error: no matching function for call to 'Player::Player()'|
>C:\Development\Libraries\boost\boost\serialization\access.hpp|132|note: candidates are:|
>C:\Development\Projects\Roguelike\Roguelike\player.cpp|8|note: Player::Player(int, int)|
>C:\Development\Projects\Roguelike\Roguelike\player.cpp|8|note:   candidate expects 2 arguments, 0 provided|
>C:\Development\Projects\Roguelike\Roguelike\player.cpp|3|note: Player::Player(bool)|
>C:\Development\Projects\Roguelike\Roguelike\player.cpp|3|note:   candidate expects 1 argument, 0 provided|
>C:\Development\Projects\Roguelike\Roguelike\player.h|12|note: Player::Player(const Player&)|
>C:\Development\Projects\Roguelike\Roguelike\player.h|12|note:   candidate expects 1 argument, 0 provided|
||=== Build failed: 1 error(s), 5 warning(s) (0 minute(s), 4 second(s)) ===|

Thanks very much. If any other information is required, I will append it.

Upvotes: 2

Views: 2194

Answers (2)

sehe
sehe

Reputation: 393134

In addition to what Joachim said, in some cases you will not be able to make a type default-constructible (especially when you're adding non-intrusive serialization to types from a 3rdparty library).

In that case learn about the load_construct_data customization point:

Non-default Constructors

This mechanism is already automatically employed for you e.g. in the deserialization of STL containers whose element type has no default constructor.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409196

The error message is pretty clear:

no matching function for call to 'Player::Player()'

You must have a default constructor in your class.

Upvotes: 2

Related Questions