I have the following minimal example reproducing an error in my code:
#include <unordered_map>
#include <iostream>
class B
{
public:
B(int b) : m_b{ b } {}
int m_b;
};
int main()
{
using std::cout, std::endl;
std::unordered_map<int, B> ab{};
ab[1] = B(3);
//ab.insert(std::pair<int, B>(1, B(3)));
cout << ab[1].m_b << endl;
}
This fails with a long and unwieldy error which basically amounts to saying that there is no constructor for B without any arguments. The error stems from ab[1] = B(3) Why is that needed? And why does using insert instead of operator[] not need that constructor?
Bonus points for why this line in my original code:
Vec2 pos{ m_orbits[&p].positionAtTime(m_time + dt) };
also requires a non - parameterized constructor. I could not reproduce that error in my minimal example, but m_orbits is an unordered map with pointers to Particle objects as keys and Orbit objects as values. positionAtTime is a const member function of Orbit that calculates the position of a particle in the orbit at a certain time.
Why is [a constructor for
Bwithout any arguments] needed?
This is because std::map::operator[] required the mapped_type (i.e. in your case B) to be default constructable.
- Inserts
value_type(key, T())if the key does not exist. This function is equivalent to returninsert(std::make_pair(key, T())).first->second;
key_typemust meet the requirements of CopyConstructible.mapped_typemust meet the requirements of CopyConstructible and DefaultConstructible. If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise) and a reference to it is returned.
When you provide a user defined constructor (i.e. B(int b)), the compiler will not generate a default constructor automatically, and thereby A can not be default construable.
If some user-declared constructors are present, the user may still force the automatic generation of a default constructor by the compiler that would be implicitly-declared otherwise with the keyword default.
Hence, the above error!
why does using
insertinstead ofoperator[]not need that constructor?
Because std::map::insert relies on the value_type (i.e. std::pair<const Key, T>). For your ab this is std::pair<const int, B>. From the cppreference.com the function overloads:
1-3) Inserts value. The overload (2) is equivalent to
emplace(std::forward<P>(value))and only participates in overload resolution ifstd::is_constructible<value_type, P&&>::value == true.4-6) Inserts value in the position as close as possible, just prior(since C++11), to hint. The overload (5) is equivalent to
emplace_hint(hint, std::forward<P>(value))and only participates in overload resolution ifstd::is_constructible<value_type, P&&>::value == true.
So as long as B is constructable the std::pair<const int, B> also can be constructed and std::map::insert can be work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With