Working with an STL list today. First time using one, and I'm not terribly familiar with the member functions, and I'm not sure I fully understand iterators. Non-the-less, I have done the research, and cannot seem to understand why the insert function from the STL list is demanding I pass it 3 arguments
note: candidate expects 3 arguments, 2 provided
Houses.insert(it,temp);
here is a segement of my code. Just for reference, this bit appears multiple times throughout, and the error crops up at every instance.
temp = new WolfDen;
it = Houses.begin();
Houses.insert(it,temp);
temp -> setDimensions();
Houses is my STL list of "homes". WolfDen is a derived class of homes. temp is homes pointer, and it is my list iterator.
Based on the comments Houses
is probably defined as
std::list<Home> Houses;
and WolfDen
inherits from Home;
class WolfDen : public Home
Since you probably intend to use the whole WolfDen
object, you need to store the pointer:
std::list<Home *> Houses;
or in modern C++ (since C++11):
std::list<std::unique_ptr<Home>> Houses;
If you use the bare pointer variant std::list<Home *>
, be sure to delete the objects pointed to, once you are done with them. E.g. right before leaving the scope in which Houses
is defined do
for (std::list<Home *>::const_iterator homeIt = Houses.begin(),
homeEnd = Houses.end();
homeIt != homeEnd; ++homeIt)
{
delete *homeIt;
}
If you stay with your definition as std::list<Home>
, the following insert statement will compile:
Houses.insert(it,*temp);
But this would insert another Home
object into Houses
which is a copy only of the Home
part of the WolfDen
object *temp
stored at the location pointed to by temp
. (The new object will be Houses.front()
)
The subsequent modification
temp->setDimensions();
will only modify the original object *temp
and not Houses.front()
. Also, the object *temp
will probably leak, unless you add
delete temp;
at the end of your code.
However, it is much better, not to use pointers at all:
Home temp;
temp.setDimensions();
it = Houses.begin();
Houses.insert(it,temp);
(Note, that class WolfDen
is not used, since only the Home
part will be used anyway.)
note: candidate expects 3 arguments, 2 provided
To understand this, have a look at http://en.cppreference.com/w/cpp/container/list/insert: The version you intend to call is version (1) of std::list::insert
iterator insert( iterator pos, const T & value ); (1)
where T is Home. I.e.
iterator insert( iterator pos, const Home & value );
For the parameter pos
you provide an argument of type std::list<Home>::iterator
, which is fine. But for the parameter value
you provide an argument of type Home *
(or possibly WolfDen *
which converts to Home *
), which is a pointer. Pointers do not convert to values (or references to values in this case) implicitly. The match with the version (1) therefore fails.
However, pointers convert to integer types implicitly. Since there are other versions of std::list::insert
, the compiler tries these, as well. The first two provided arguments match to version (3) in http://en.cppreference.com/w/cpp/container/list/insert:
void insert( iterator pos, size_type count, const T & value ); (3)
The pointer of type Home *
converts to size_type
. But then the third argument value
is missing... Some compilers are more elaborate and list the possible candidates and also more information about the failed matches.
If value
would not be needed, you code might have compiled. Since pointers are usually converted to rather large values, your application would have added a rather large number of entries to Houses
. (You can try this by changing your code to Houses.insert(it,temp, WolfDen());
. But be prepared to run out of memory ;-)).