简体   繁体   中英

How to insert class objects to map correctly without pointers?

this is my code:

LoggedUser.h

#pragma once
#include <string>

using std::string;

class LoggedUser {
private:
    string m_username;
public:
    LoggedUser(string username);
    string getUsername() const;
    bool operator==(LoggedUser loggedUser) const;
};

Room.h

#pragma once
#include <LoggedUser.h>
#include <string>
#include <vector>

using std::vector;
using std::string;

typedef struct RoomData {
    unsigned int id = 0;
    string name;
    unsigned int maxPlayers = 4;
    const unsigned int timePerPlay = 10;
    bool isActive = false;

    RoomData& operator=(const RoomData& roomData) {
        this->id = roomData.id;
        this->isActive = roomData.isActive;
        this->maxPlayers = roomData.maxPlayers;
        this->name = roomData.name;
        return *this;
    }
} RoomData;

class Room {
private:
    RoomData m_metadata;
    vector<LoggedUser> m_users;
public:
    Room(const Room& room);
    Room(RoomData roomData, LoggedUser loggedUser);
    int getUserIndex(const LoggedUser& loggedUser);
    void addUser(LoggedUser loggedUser);
    void removeUser(LoggedUser loggedUser);
    vector<LoggedUser> getAllUsers();

    unsigned int getId();
    string getName();
    unsigned int getMaxPlayers();
    bool getIsActive();
};

RoomManager.h

#pragma once
#include <map>
#include "Room.h"

class RoomManager {
private:
    std::map<unsigned int, Room> m_rooms;
public:
    void createRoom(LoggedUser loggedUser, RoomData roomData);
}

RoomManager.cpp

#include "RoomManager.h"

void RoomManager::createRoom(LoggedUser loggedUser, RoomData roomData)
{
    m_rooms[roomData.id] = Room(roomData, loggedUser);
}

The problem is in the file RoomManager.cpp in the function createRoom i'm trying to insert to the map<unsigned int, Room>, a room by his id, but i get this error "C2512 'Room::Room': no appropriate default constructor available"

now, i know i can fix this by inserting a pointer of Room instead of the object itself, but i want to know if there is a way to do it without pointers, just so i know what was the problem in my code. Thanks for everyone who helping.

In the m_rooms[roomData.id] = Room(roomData, loggedUser); statement you use the std::map::operator[] , which...

...returns a reference to the value that is mapped to a key equivalent to (requested) key, performing an insertion if such key does not already exist .

Thus, we may use the operator only if the mapped_type has a default constructor. Since to insert a "fallback" a value into the map (if we access a key that is not in there yet) it will need to default construct one on the fly.

But since you did provide non-default constructors for Room , the compiler does not synthesizes the default one for you. Thus, the Room is not DefaultInsertable.

So we can handle this by simply introducing a defaulted default constructor :

class Room {
    // Other private members as before
public:
    // Other public members as before
    Room() = default;
};

Lesson learned: std::map::operator[] require mapped_type to be DefaultInsertable . For more, refer to the documentation .

You are using operator[] to insert an item into the std::map . This operation requires that the inserted item is DefaultConstructible 1 .

The Room class is not DefaultConstructibel , as explained in the other answer by @rawrex.

If you cannot or do not want to add a default constructor, you can also use the insert() function to insert an item. This function does not have the above requirement.

m_rooms.insert(std::make_pair(roomData.id, Room(roomData, loggedUser)));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM