C++ inserting object with constructor into map - c++

I was trying to methods to insert into a map, inserting a pair into a map works fine, the code looks like this:
type insert(){
map<int,MyClass> myMap;
MyClass myObj(parameter);
myMap.insert(pair<int,MyClass>(0,myObj));
...
return myMap;
}
However, I decide to use the other way, basically:
map[key] = value;
And, it look like this:
type insert(){
map<int,MyClass> myMap;
MyClass myObj(parameter);
myMap[i] = myObj;
....
return myMap;
}
compiler will give an error saying: "no matching function for call to myObj::myObj(), candidates are: " and it gives my self defined constructor.
My guess is that when using the indexing way to cast to a map, if I were to pass in an object, then it will automatically call its default constructor with no parameter. But since I have already got a self defined constructor with parameter, it will therefore give an error. Therefore, I tried creating a map in which the value is an object, and the object has only default constructor. This way, compiler is not complaining.
My problem is I don't find any document confirming my idea. If it is right, why does the map with value of object made to call the default constructor rather than existing constructor?

The problem is that std::map::operator[] will actually return a reference to the object on the given index and if there is non, default construct one. Your assignment takes place after acquiring a reference.
Use std::map::emplace to directly construct an object in place:
myMap.emplace(i, parameter);

What happens when you call
myMap[i] = myObj;
is that, if there is no element with key i, one is inserted with a value initialized (which for a user defined type means default constructed) mapped type. You then assign to it the value on the RHS of the assignment. The first part requires that the type be default constructable.

std::map requires your type must have a no-argument constructor. See here for a discussion of why.

Related

C++ Error: no matching function for call - when used in class constructor [duplicate]

See also
C++ standard list and default-constructible types
Not a major issue, just annoying as I don't want my class to ever be instantiated without the particular arguments.
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
This gives me the following g++ error:
/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()’
This compiles fine if I add a default constructor; I am certain it's not caused by incorrect syntax.
This issue comes with operator[]. Quote from SGI documentation:
data_type& operator[](const key_type& k) - Returns a reference to the object
that is associated with a particular
key. If the map does not already
contain such an object, operator[]
inserts the default object
data_type().
If you don't have default constructor you can use insert/find functions.
Following example works fine:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.
Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.
Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:
From 20.1.4.1:
The default constructor is not
required. Certain container class
member function signatures specify the
default constructor as a default
argument. T() must be a well-defined
expression ...
So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.
The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible and Assignable.
There are also other specific requirements for particular containers as well, such as being Comparable (e.g. for keys in a map).
Incidentally, the following compiles with no error on comeau:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
So this might be a g++ problem.
Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).
Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.
assume you have the following
class Person
{
public:
Person(int age) :age(age){}
Person() {} // default ctor
int age;
};
map<int, Person> m;
// accessing not-existent key, results in assigning default value to that key
m[10];
// creates default object for key:20 first then assigns age
m[20].age = 32;
what should happen if you wanna assign age for a nonexistent key?
for languages with null type such as javascript the map returns null and its is up to user to check for it before accessing the object or its internal fields.
c++ went a different approach and creates the Person using default constructor so the null is avoided all together
Check if:
You forgot the ';' after class declaration.
MyType should've been declared accordingly.
No default constructor there...
The std::map declaration seems correct, I think.
Most likely because std::pair requires it. std::pair holds two values using value semantics so you need to be able to instantiate them without parameters. So the code uses std::pair in various places to return the map values to the caller and this is commonly done by instantiating an empty pair and assigning the values into it before returning the local pair.
You could get around this with smart pointers using a map<int, smartptr<MyClass> > but that adds the overhead of checking for null pointers.

Error when creating instance of unordered map [duplicate]

See also
C++ standard list and default-constructible types
Not a major issue, just annoying as I don't want my class to ever be instantiated without the particular arguments.
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
This gives me the following g++ error:
/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()’
This compiles fine if I add a default constructor; I am certain it's not caused by incorrect syntax.
This issue comes with operator[]. Quote from SGI documentation:
data_type& operator[](const key_type& k) - Returns a reference to the object
that is associated with a particular
key. If the map does not already
contain such an object, operator[]
inserts the default object
data_type().
If you don't have default constructor you can use insert/find functions.
Following example works fine:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.
Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.
Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:
From 20.1.4.1:
The default constructor is not
required. Certain container class
member function signatures specify the
default constructor as a default
argument. T() must be a well-defined
expression ...
So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.
The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible and Assignable.
There are also other specific requirements for particular containers as well, such as being Comparable (e.g. for keys in a map).
Incidentally, the following compiles with no error on comeau:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
So this might be a g++ problem.
Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).
Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.
assume you have the following
class Person
{
public:
Person(int age) :age(age){}
Person() {} // default ctor
int age;
};
map<int, Person> m;
// accessing not-existent key, results in assigning default value to that key
m[10];
// creates default object for key:20 first then assigns age
m[20].age = 32;
what should happen if you wanna assign age for a nonexistent key?
for languages with null type such as javascript the map returns null and its is up to user to check for it before accessing the object or its internal fields.
c++ went a different approach and creates the Person using default constructor so the null is avoided all together
Check if:
You forgot the ';' after class declaration.
MyType should've been declared accordingly.
No default constructor there...
The std::map declaration seems correct, I think.
Most likely because std::pair requires it. std::pair holds two values using value semantics so you need to be able to instantiate them without parameters. So the code uses std::pair in various places to return the map values to the caller and this is commonly done by instantiating an empty pair and assigning the values into it before returning the local pair.
You could get around this with smart pointers using a map<int, smartptr<MyClass> > but that adds the overhead of checking for null pointers.

Using a prvalue to create a shared_pointer

I have a class functionCombiner which constructor looks like this
FunctionCombiner::FunctionCombiner(std::vector<std::shared_ptr<valuationFunction>> Inner_) : Inner(std::move(Inner_)), valuationFunction("", 0) //<- Needs to initalize itself even though it gets all data from inner functions.
{
}
In my main class I'm calling it like this:
vector<std::shared_ptr<valuationFunction>> combinedStillFrontFunctions{ stillFrontStock, stillFrontEuropeanCall };
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>(combinedStillFrontFunctions);
What I would like to be able to do is reduce that to one line by constructing it in place like so
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>({ stillFrontStock, stillFrontEuropeanCall });
Which the compiler doesn't like. Is there a way to make this work? This works obviously:
FunctionCombiner StillFrontFunctions({ stillFrontStock, stillFrontEuropeanCall });
But I need it to be a shared pointer.
(Shorting some names to make the example readable w/o horizontal scrollbars. You should consider doing the same...)
Passing {x,y} to make_shared() is attempting to forward a brace-enclosed initializer list, not to initialize the value in the shared pointer, but the temporary object its constructor takes. It's not something that can be forwarded since it's not a full expression on its own. So make a temporary vector with those values:
... = make_shared<FunComb>(vector<shared_ptr<valFun>>{FS, FEC});
Another approach may be to change FunComb's constructor to be a (or add a new) variadic constructor, removing the need to pass in a vector just to hold the inputs.

declaring a map with its value type is a class [duplicate]

See also
C++ standard list and default-constructible types
Not a major issue, just annoying as I don't want my class to ever be instantiated without the particular arguments.
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
This gives me the following g++ error:
/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()’
This compiles fine if I add a default constructor; I am certain it's not caused by incorrect syntax.
This issue comes with operator[]. Quote from SGI documentation:
data_type& operator[](const key_type& k) - Returns a reference to the object
that is associated with a particular
key. If the map does not already
contain such an object, operator[]
inserts the default object
data_type().
If you don't have default constructor you can use insert/find functions.
Following example works fine:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.
Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.
Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:
From 20.1.4.1:
The default constructor is not
required. Certain container class
member function signatures specify the
default constructor as a default
argument. T() must be a well-defined
expression ...
So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.
The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible and Assignable.
There are also other specific requirements for particular containers as well, such as being Comparable (e.g. for keys in a map).
Incidentally, the following compiles with no error on comeau:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
So this might be a g++ problem.
Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).
Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.
assume you have the following
class Person
{
public:
Person(int age) :age(age){}
Person() {} // default ctor
int age;
};
map<int, Person> m;
// accessing not-existent key, results in assigning default value to that key
m[10];
// creates default object for key:20 first then assigns age
m[20].age = 32;
what should happen if you wanna assign age for a nonexistent key?
for languages with null type such as javascript the map returns null and its is up to user to check for it before accessing the object or its internal fields.
c++ went a different approach and creates the Person using default constructor so the null is avoided all together
Check if:
You forgot the ';' after class declaration.
MyType should've been declared accordingly.
No default constructor there...
The std::map declaration seems correct, I think.
Most likely because std::pair requires it. std::pair holds two values using value semantics so you need to be able to instantiate them without parameters. So the code uses std::pair in various places to return the map values to the caller and this is commonly done by instantiating an empty pair and assigning the values into it before returning the local pair.
You could get around this with smart pointers using a map<int, smartptr<MyClass> > but that adds the overhead of checking for null pointers.

Why does the C++ map type argument require an empty constructor when using []?

See also
C++ standard list and default-constructible types
Not a major issue, just annoying as I don't want my class to ever be instantiated without the particular arguments.
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
This gives me the following g++ error:
/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()’
This compiles fine if I add a default constructor; I am certain it's not caused by incorrect syntax.
This issue comes with operator[]. Quote from SGI documentation:
data_type& operator[](const key_type& k) - Returns a reference to the object
that is associated with a particular
key. If the map does not already
contain such an object, operator[]
inserts the default object
data_type().
If you don't have default constructor you can use insert/find functions.
Following example works fine:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.
Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.
Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:
From 20.1.4.1:
The default constructor is not
required. Certain container class
member function signatures specify the
default constructor as a default
argument. T() must be a well-defined
expression ...
So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.
The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible and Assignable.
There are also other specific requirements for particular containers as well, such as being Comparable (e.g. for keys in a map).
Incidentally, the following compiles with no error on comeau:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
So this might be a g++ problem.
Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).
Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.
assume you have the following
class Person
{
public:
Person(int age) :age(age){}
Person() {} // default ctor
int age;
};
map<int, Person> m;
// accessing not-existent key, results in assigning default value to that key
m[10];
// creates default object for key:20 first then assigns age
m[20].age = 32;
what should happen if you wanna assign age for a nonexistent key?
for languages with null type such as javascript the map returns null and its is up to user to check for it before accessing the object or its internal fields.
c++ went a different approach and creates the Person using default constructor so the null is avoided all together
Check if:
You forgot the ';' after class declaration.
MyType should've been declared accordingly.
No default constructor there...
The std::map declaration seems correct, I think.
Most likely because std::pair requires it. std::pair holds two values using value semantics so you need to be able to instantiate them without parameters. So the code uses std::pair in various places to return the map values to the caller and this is commonly done by instantiating an empty pair and assigning the values into it before returning the local pair.
You could get around this with smart pointers using a map<int, smartptr<MyClass> > but that adds the overhead of checking for null pointers.