This is my CreateCustomer method:
CustomerData Database::createCustomer(std::string const& name) {
CustomerData data(customersDb.size()+1, name);
customersDb[data.number()] = data;
// customersDb.insert(std::pair<uint, CustomerData>(data.number(), data));
return data;
}
Constructor of class CustomerData:
CustomerData::CustomerData(uint number, std::string const& name) {
m_number = number;
m_name = name;
}
Incorrect line is this one:
customersDb[data.number()] = data;
Thing is, the next line works. I can't figure it out and can't use insert because accessing element with [] brackets doesn't work either.
I've tried even creating copy constructor but with no effect:
CustomerData::CustomerData(CustomerData &data) {
m_number = data.number();
m_name = data.name();
}
These are the errors:
Database.cpp:5: instantiated from here
stl_map.h:450: error: no matching function for call to 'CustomerData::CustomerData()'
CustomerData.h:18: candidates are: CustomerData::CustomerData(CustomerData&)
CustomerData.h:17: note: CustomerData::CustomerData(uint, const std::string&)
I use Mingw.
operator[] with the standard map template default-constructs an element with the given key if none already exists.
Your element type has no default constructor, so this cannot happen.
You'll have to use .insert instead.
customersDb.insert(make_pair(data.number(), data));
I can't figure it out and can't use insert because accessing element with [] brackets doesn't work either.
To modify an existing element, retrieve an iterator with .find, dereference and do your thing.
yourMapType::iterator it = customersDb.find(data.number());
if (it != customersDb.end())
*it = data;
It doesn't work because operator[] actually first default constructs the value, and then assigns to it.
You can either provide a default constructor, or use this call:
customersDb.insert( std::map< uint, CustomerData >::value_type (data.number(), data) );
You need to provide a default constructor for your CustomerData class.
CustomerData::CustomerData()
{
}
Or you implement a code in such a way that it only calls the constructor which you have provided for your class. It is needed by [] to default construct an element.
First one looks a better option.
Reason for error:
When you provide any constructor for your own class, the compiler does not generate the default no argument constructor and your code needs one and hence the error.
Read the error, it's in there :)
stl_map.h:450: error: no matching function for call to 'CustomerData::CustomerData()'
It looks like the compiler thinks you're not actually passing any information to the function.
It does recognize these two alternatives :
CustomerData.h:18: candidates are: CustomerData::CustomerData(CustomerData&)
CustomerData.h:17: note: CustomerData::CustomerData(uint, const std::string&)
But both take arguments, which you're not passing.
You need to make sure there is default (blank) constructor so the type can be constructed without args.
myclass(); //implement somewhere
you can also provide default args
myclass(const std::string& value="hello"); //implement somewhere
in C++11 you can do this
myclass()=default; //implementation will be generated
It is trying to call the constructor on your CustomerData class, but it doesn't exist. I'm pretty sure this is something to do with how the standard map works internally. The value of the map must have a default constructor. This would normally be generated by the compiler, but as you have already provided another constructor it was not generated.
Related
Please first look the code as follow:
class StrBlob
{
public:
StrBlob();
// ....
private:
std::shared_ptr<std::vector<std::string> > data;
}
//initializer empty into data ;
StrBlob::StrBlob()
// : data(std::make_shared<std::vector<std::string> >()) // compile success
{
// data(std::make_shared<std::vector<std::string> >()); // compile error
}
int main()
{
// this statement can compile
std::shared_ptr<std::vector<std::string> >data(std::make_shared<std::vector<std::string> >());
return 0;
}
I want to know why the statement above compiles occurs error? ?
error: no match for call to ‘(std::shared_ptr<std::vector<std::__cxx11::basic_string<char> > >)
(std::shared_ptr<std::vector<std::__cxx11::basic_string<char> > >)’
data(std::make_shared<std::vector<std::string> >());
corresponding knowledge quoted in C++Primer 5th (Chapter 7.5) as follows:
We can often, but not always , ignore the distinction between whether a member is initialized or assigned. Members that are const or references must be initialized. Similarly, members that are of a class type that does not define a default constructor also must be initialized
First I will share my thought.the 'data' member is default initialized before the constructor body starts executing. right? so,the 'data' member inside constructor will copy the object created from the function make_shared.right?
The first one compiles successfully because you initialize data in the member initializer list and such syntax is perfectly valid here. Check this for more information.
The second one is equal to data(...). It is not a constructing of data object, compiler sees it like an attempt of calling operator() for the data member which is already created (and it says about it in the error message).
Finally inside the main function you simply use shared_ptr copy constructor to create data from the shared_ptr returned by make_shared.
If you want to initialize data object later for many reasons, you can use std::shared_ptr default constructor in StrBlob initialization list and in the body of the StrBlob constructor - the reset function:
StrBlob::StrBlob()
: data()
{
data.reset(new std::vector<std::string>());
}
I'm getting the error:
error: no matching function for call to 'A::A()'
note: candidates are: A::A(const A&)
note: A::A(const std::string&, size_t)
From this:
#include <map>
#include <string>
using std::map;
using std::string;
class A {
public:
string path;
size_t size;
A (const string& p, size_t s) : path(p), size(s) { }
A (const A& f) : path(f.path), size(f.size) { }
A& operator=(const A& rhs) {
path = rhs.path;
size = rhs.size;
return *this;
}
};
int main(int argc, char **argv)
{
map<string, A> mymap;
A a("world", 1);
mymap["hello"] = a; // <----- here
A b(mymap["hello"]); // <----- and here
}
Please tell me why the code wants a constructor with no parameters.
Because map requires DefaultConstructible values, since when using subscript operator and the key is not found it adds it mapped to a default constructed value.
In general a default constructor is not required for a map item value.
It was required in C++03, but that requirement was dropped in C++11, which often instead of posing container-wide requirements uses a more fine grained requirement scheme with requirements on the use of particular member functions.
The map::operator[] is one such member function, because it will create an item with the given key and a default-constructed value, if an item with the key doesn't exist.
This is also the reason why there isn't a const version of map::operator[]: it potentially modifies the map.
In C++11 and later you can use the at accessor to access an item with a given key in a const map, without the verbosity & complexity of a find.
Since map::at doesn't attempt to create an item, it doesn't require the item type to be default constructible.
And so one practical solution for your problem is to use map::at instead of map::operator[].
mymap["hello"] can attempt to create a value-initialized A, so a default constructor is required.
If you're using a type T as a map value (and plan to access value via operator[]), it needs to be default-constructible - i.e. you need a parameter-less (default) constructor. operator[] on a map will value-initialize the mapped value if a value with the key provided is not found.
Long time without using C++, but If I recall correctly if you don't define a constructor for a class the compiler will create a paramless one for you. As soon as you define a constructor with parameters the compiler won't create a paramless one for you, so, you are required to create one. This added to what K-ballo exposed leads to your errors.
I think the question is pretty simple and it can be shrunk in few words such "which operator does the compiler overload automatically?"
I've got an idea about what is going on but I'm currently missing some details able to explain me why it's working as it's.
Unfortunately I did not find anything of useful into my Stroustrup's C++ reference and I'm pretty sure that somebody of you can help me figuring out what's happening.
Let's open the discussion: here's a little snapshot something similar to the code I was looking at:
class MyPair : public pair<string,string>
{
public:
MyPair()
{
pair<string,string>();
}
};
So far nothing of strange, as widely discussed in the thread
What are all the member-functions created by compiler for a class? Does that happen all the time?
the compiler will automatically generate a default version of copy constructor a copy assignment operator and a destructor but not a default constructor just because I redefined my own.
Thanks to the compiler I'll be able to assign a new object at the creation time using the default copy constructor and to use the assignment operator just after the creation of an object, as showed here:
//default copy constructor
MyPair mypair1 = mypair;
MyPair mypair2;
//default assignment operator
mypair2 = mypair1
Until now, everything works as designed.
Imagine now that I would like, for some unknown reason, to assign a string object to MyPair object, like it follows:
int main()
{
pair<string,string> aPair;
MyPair mypair;
string mystring("test");
//ERROR
mypair = mystring;
return 0;
}
Before I tested out this line of code, I was expecting that the compiler would have complained about (because I didn't provide to it any explicit overload of the operator=, so by itself is not able to assign a string to the created object), and indeed it returned me a quite self-explicative error, like:
test.cpp:36:13: error: no match for ‘operator=’ in ‘mypair = mystring’
test.cpp:36:13: note: candidate is:
test.cpp:7:7: note: MyPair& MyPair::operator=(const MyPair&)
Now, imagine to complete the MyPair class by adding the following method:
MyPair(const string& astring)
{
pair<string,string>(astring,string());
}
Suddenly, the code starts compiling, without giving anymore any kind of error.
To my eyes it seems that the above method provided to the compiler some kind of cleverness; it started generating the missing MyPair& MyPair::operator=(const string &s).
I have to admit that it sounds really brilliant, but I cannot understand exactly why it happens.
Would it mean that for each additional constructor I put in place into MyPair the coplier will generate an additional overloaded operator= that makes my class being copy assignable to the specified reference just because of that?
MyPair(const string& astring) is an implicit conversion constructor. Your string is first used to create a new MyPair which is then assigned to your object. You can disallow this behavior by marking it explicit:
explicit MyPair(const string& astring)
This prevents implicit conversion, so
mypair = mystring;
is illegal, while
mypair = MyPair(mystring);
still works.
Just to inform you that your way of initializing the base class member is not right.
MyPair()
{
pair<string,string>();
}
should instead be:
MyPair() : pair<string, string>()
{
}
and
MyPair(const string& astring)
{
pair<string,string>(astring,string());
}
should instead be:
MyPair(const string& astring) : pair<string, string>(astring, string())
{
}
As for why assignment is working, a temporary of MyPair is created using the constructor and is used as the argument to the assignment operator.
I'm getting the error:
error: no matching function for call to 'A::A()'
note: candidates are: A::A(const A&)
note: A::A(const std::string&, size_t)
From this:
#include <map>
#include <string>
using std::map;
using std::string;
class A {
public:
string path;
size_t size;
A (const string& p, size_t s) : path(p), size(s) { }
A (const A& f) : path(f.path), size(f.size) { }
A& operator=(const A& rhs) {
path = rhs.path;
size = rhs.size;
return *this;
}
};
int main(int argc, char **argv)
{
map<string, A> mymap;
A a("world", 1);
mymap["hello"] = a; // <----- here
A b(mymap["hello"]); // <----- and here
}
Please tell me why the code wants a constructor with no parameters.
Because map requires DefaultConstructible values, since when using subscript operator and the key is not found it adds it mapped to a default constructed value.
In general a default constructor is not required for a map item value.
It was required in C++03, but that requirement was dropped in C++11, which often instead of posing container-wide requirements uses a more fine grained requirement scheme with requirements on the use of particular member functions.
The map::operator[] is one such member function, because it will create an item with the given key and a default-constructed value, if an item with the key doesn't exist.
This is also the reason why there isn't a const version of map::operator[]: it potentially modifies the map.
In C++11 and later you can use the at accessor to access an item with a given key in a const map, without the verbosity & complexity of a find.
Since map::at doesn't attempt to create an item, it doesn't require the item type to be default constructible.
And so one practical solution for your problem is to use map::at instead of map::operator[].
mymap["hello"] can attempt to create a value-initialized A, so a default constructor is required.
If you're using a type T as a map value (and plan to access value via operator[]), it needs to be default-constructible - i.e. you need a parameter-less (default) constructor. operator[] on a map will value-initialize the mapped value if a value with the key provided is not found.
Long time without using C++, but If I recall correctly if you don't define a constructor for a class the compiler will create a paramless one for you. As soon as you define a constructor with parameters the compiler won't create a paramless one for you, so, you are required to create one. This added to what K-ballo exposed leads to your errors.
I am trying to make use of the unique_ptr from C++x0, by doing
#include <memory>
and comping with -std=c++0x, however it is throwing up many errors this being an example.
/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../include/c++/4.4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = Descriptor, _Tp_Deleter = std::default_delete<Descriptor>]’
UPDATE****
This is what I am trying to do, I have removed typedefs so you can see clearly the types
static std::unique_ptr<SomeType> GetSomeType()
{
std::unique_ptr<SomeType> st("Data","Data2",false);
std::unique_ptr<OtherType> ot("uniportantconstructor data");
st->Add(ot);
return st;
}
//Public method of SomeType
void Add(std::unique_ptr<OtherType> ot)
{
//otmap is std::map<std::string,std::unique_ptr<OtherType> >
//mappair is std::Pair<std::string,std::unique_ptr<OtherType> >
otMap.Insert(mappair(ot->name(),ot));
}
UPDATE:
If my class SomeType has a method that returns a element from the map (using the key) say
std::unique_ptr<OtherType> get_othertype(std::string name)
{
return otMap.find(name);
}
that would enure the caller would recieve a pointer to the one in the map rather than a copy?
std::unique_ptr<OtherType> ot("unimportant constructor data");
st->Add(ot);
You cannot pass an lvalue to a function accepting a unique_pointer, because unique_pointer has no copy constructor. You must either move the lvalue (to cast it to an xvalue) or pass a prvalue:
// pass an xvalue:
std::unique_ptr<OtherType> ot("unimportant constructor data");
st->Add(std::move(ot));
// note: ot is now empty
// pass a prvalue:
st->Add(std::unique_ptr<OtherType>("unimportant constructor data"));
Inside the Add method, things are a little more complicated. First, you have to move from ot, because formal parameters are always lvalues (since they have names). Second, you cannot move from ot and get ot->name() as arguments to the mappair function, because the order of argument evaluation is unspecified in C++. So we have to get ot->name() in a separate statement before moving from ot:
void Add(std::unique_ptr<OtherType> ot)
{
auto name = ot->name();
otMap.Insert(mappair(name, std::move(ot)));
}
Hope this helps. Note that under no (sane) circumstances can two unique_ptr objects point to the same thing. If you need that functionality, unique_ptr is not what you want.
It looks like you're trying to use the copy constructor. There isn't one. If your calling code looks like this:
T *ptr = /* whatever */;
std::unique_ptr<T> up = ptr;
You have to change the second line to this:
std::unique_ptr<T> up (ptr);
The original version is (basically) implicitly turning the assignment into:
std::unique_ptr<T> up (std::unique_ptr<T>(ptr));
The copy constructor has been deleted. "deleted function" is C++0x-speak for explicitly removing an implicit special member function. In this case, the copy constructor.
As #Steve said you're probably using the copy constructor, unique_ptr does not support copy semantics, if you want to move to value to another unique_ptr you're have to move it.
unique_ptr<T> other = std::move(orig); // orig is now null