Mihai
Mihai

Reputation: 229

Can't push back a class object because of constructor

I have this piece code where I try to push into a vector an already constructed element from an unordered_map:

class A {
public:
    A(const std::string& a) {}
}

int main() {
    std::unordered_map<std::string, A> map {{"A", A("A")}, {"B", A("B")}};
    std::vector<A> vec;
    vec.push_back(map["A"]);
}

But why I'm getting errors regarding to the the vector's push_back:

/usr/local/include/c++/6.3.0/tuple:1586:70: error: no matching function for call to 'A::A()'
         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
                                                                      ^
main.cpp:8:9: note: candidate: A::A(const string&)
         A(const std::string& a) {}
         ^
main.cpp:8:9: note:   candidate expects 1 argument, 0 provided
main.cpp:6:7: note: candidate: constexpr A::A(const A&)
 class A {
       ^
main.cpp:6:7: note:   candidate expects 1 argument, 0 provided
main.cpp:6:7: note: candidate: constexpr A::A(A&&)
main.cpp:6:7: note:   candidate expects 1 argument, 0 provided

Upvotes: 3

Views: 1097

Answers (3)

Jonas
Jonas

Reputation: 7017

The issue is that when using std::unordered_map::operator[] (ref) your mapped_type (A) must be default constructible, the key_type must be move constructible which is not an issue with std::string in your example.

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

class A {
public:
    A(const std::string& a) {}
    A() {} // Default constructor
};

int main() {
    std::unordered_map<std::string, A> map {{"A", A("A")}, {"B", A("B")}};
    std::vector<A> vec;
    vec.push_back(map["A"]); // Requires default constructor
    vec.push_back(map.at("A")); // Do NOT requires default constructor
}

Upvotes: 3

acraig5075
acraig5075

Reputation: 10756

With the question having a C++11 tag, the above answers could mention that you don't need an actual implementation of a default constructor, but that you can use the =default specifier to convey that is the only reason it's needed.

class A {
public:
    A() = default;
    A(const std::string& a) {}
}

Upvotes: 3

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

std::map::operator[] requires the mapped type (in your case, A) to be default-insertable, so you have to provide a default constructor, which you have not, for example:

class A {
public:
    A(){}
    A(const std::string& a) {}
}

Upvotes: 2

Related Questions