Detecting and fixing Invalid Iterator - c++

I have a strange problem that rarely happens relating to invalidated STL iterators that I've simplified in the example code below.
Foo.h
#include "Bar.h"
#include <map>
class Foo
{
std::map<int, Bar*> test;
public:
Foo() {}
void Update();
void AddEntry(int i, Bar* bar);
void DeleteEntry(int i);
};
Foo.cpp
#include "Foo.h"
void Foo::Update() {
for(auto iter = test.rbegin(); iter != test.rend(); iter++) {
iter->second->DoThingOne();
iter->second->DoThingTwo(); // BREAKS ON 2nd ITERATION
}
}
void Foo::AddEntry(int i, Bar* b) {
test[i] = b;
}
void Foo::DeleteEntry(int i) {
delete test[i];
test.erase(i);
}
Bar.h
class Foo;
class Bar
{
Foo* f;
static int count;
public:
friend class Foo;
Bar(Foo* f_);
void DoThingOne();
void DoThingTwo();
};
Bar.cpp
#include "Bar.h"
#include "Foo.h"
int Bar::count = 0;
Bar::Bar(Foo* f_) : f(f_) {}
void Bar::DoThingOne() {
if(count++ == 1) {
f->DeleteEntry(3);
}
}
void Bar::DoThingTwo() {
// Does things
}
Main.cpp
#include "Foo.h"
int main() {
Foo* foo = new Foo();
Bar* one = new Bar(foo);
Bar* two = new Bar(foo);
Bar* three = new Bar(foo);
foo->AddEntry(1, one);
foo->AddEntry(2, two);
foo->AddEntry(3, three);
foo->Update();
return 0;
}
So basically, when Foo::Update is called, the 1st iteration of the loop proceed normally, then the 2nd iteration calls DoThingOne which deletes the entry in the map that the previous iteration of the loop just used. When DoThingTwo is called right after I get a "Debug Assertion Failed! Expression: map/set iterator not decrementable" error crashing the program.
From what I understand, iterators over maps and sets are always valid except for iterators referring to elements removed, but here the iterator is referring to the element right after the one removed. My only guess is that it has something to do with the element being removed being the first/last element and the iterator in use is then referring to the new first/last element, but I still can't find out exactly why this is happening or how to work around it. I only really have the option of detecting when this happens in the for-loop before DoThingTwo is called and trying to fix it there.
Edit: After looking at the link provided by Nemo, I changed the loop to the following and it seems to work:
void Foo::Update {
auto iter = test.end();
for(iter--; iter != test.begin(); iter--) {
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
It looks really sloppy, but this does get the job done. Since using iterator instead of reverse_iterator works, I guess it does have something to do with how reverse_iterator works compared to iterator.

Related

Insert an object pointer into a map of maps through emplace() does not work

I'm trying to insert a pointer object to a map through emplace() but it does not work.
I've created a simple representation of the problem below. I'm trying to insert to newFooList pointer object type Foo*.
I can't seem to find a way to create a type for FooMap* in std::map<int, FooMap*> m_fooMapList. Should it be done with the new on the second field of the map?
#include <iostream>
#include <utility>
#include <stdint.h>
#include <cstdlib>
#include <map>
class Foo
{
private:
int m_foobar;
public:
Foo(int value)
{
m_foobar = value;
}
void setfoobar(int value);
int getfoobar();
};
class FooMap
{
private:
std::map<int, Foo*> m_newFoo;
public:
FooMap() = default;
};
class FooMapList
{
private:
std::map<int, FooMap*> m_fooMapList;
public:
FooMapList() = default;
void insertFoo(Foo* newFooObj);
};
int Foo::getfoobar(void)
{
return(m_foobar);
}
void FooMapList::insertFoo(Foo* newFooObj)
{
if(m_fooMapList.empty())
{
std::cout << "m_fooMapList is empty" << std::endl ;
}
//m_fooMapList.emplace( newFooObj->getfoobar(), newFooObj );
// Need to find a way to insert newFooObj to m_fooMapList
m_fooMapList.second = new FooMap;
}
int main() {
FooMapList newFooList;
for (auto i=1; i<=5; i++)
{
Foo *newFoo = new Foo(i);
newFoo->getfoobar();
newFooList.insertFoo(newFoo);
}
return 0;
}
On g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
$ g++ -std=c++11 -Wall map_of_map.cpp
map_of_map.cpp: In member function ‘void FooMapList::insertFoo(Foo*)’:
map_of_map.cpp:51:18: error: ‘class std::map<int, FooMap*>’ has no member named ‘second’
m_fooMapList.second = new FooMap;
m_fooMapList is defined as
std::map<int, FooMap*> m_fooMapList;
So to insert into it, you need an int and a pointer to FooMap:
m_fooMapList.emplace(newFooObj->getfoobar(), new FooMap);
Having said that, you should use C++ value semantics and rely less on raw pointers:
std::map<int, FooMap> m_fooMapList; // no pointers
m_fooMapList.emplace(newFooObj->getfoobar(), {}); // construct objects in-place
That is, instances of FooMap can reside directly in the map itself.
That way you get better performance and avoid memory leaks.
It's also worth looking into smart pointers (e.g. unique_ptr) if you really want to work with pointers.
I am not sure if you need a map structure where the values are pointers to another map. The FooMapList class could be simple
std::map<int, FooMap> m_fooMapList;
On the other hand, the entire play with the row pointer will bring you nothing but a pain on the neck.
In case the use of
std::map<int, FooMap*> m_fooMapList; and std::map<int, Foo*> are neccesarry, I would go for smartpointers.
Following is an example code with replacing row pointers with std::unique_ptr and shows how to insert map of Foo s to map in-place. See live here
#include <iostream>
#include <utility>
#include <map>
#include <memory>
class Foo
{
private:
int m_foobar;
public:
Foo(int value): m_foobar(value) {}
void setfoobar(int value) noexcept { m_foobar = value; }
int getfoobar() const noexcept { return m_foobar; }
};
class FooMap
{
private:
std::map<int, std::unique_ptr<Foo>> m_newFoo;
// ^^^^^^^^^^^^^^^^^^^^
public:
FooMap() = default;
#if 0 // optional
// copy disabled
FooMap(const FooMap&) = delete;
FooMap& operator=(const FooMap&) = delete;
// move enabled
FooMap(FooMap&&) = default;
FooMap& operator=(FooMap&&) = default;
#endif
// provide a helper function to insert new Foo to the map of Foo s
void insertFoo(std::unique_ptr<Foo> newFooObj)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
std::cout << "inserting to FooMap..." << std::endl;
m_newFoo.emplace(newFooObj->getfoobar(), std::move(newFooObj)); // construct in place
}
};
class FooMapList
{
private:
std::map<int, std::unique_ptr<FooMap>> m_fooMapList;
// ^^^^^^^^^^^^^^^^^^^^^^^
public:
FooMapList() = default;
void insertFooMap(std::unique_ptr<Foo> newFooObj)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
if (m_fooMapList.empty())
{
std::cout << "m_fooMapList is empty" << std::endl;
}
// create FooMap and insert Foo to it.
FooMap fooMap;
const auto key = newFooObj->getfoobar();
fooMap.insertFoo(std::move(newFooObj));
// finally insert the FooMap to m_fooMapList
std::cout << "inserting to fooMapList..." << std::endl;
m_fooMapList.emplace(key, std::make_unique<FooMap>(std::move(fooMap))); // construct in place
}
};
int main()
{
FooMapList newFooList;
for (auto i = 1; i <= 5; i++)
{
auto newFoo = std::make_unique<Foo>(i);
std::cout << newFoo->getfoobar() << std::endl;
newFooList.insertFooMap(std::move(newFoo));
}
return 0;
}
Output:
1
m_fooMapList is empty
inserting to FooMap...
inserting to fooMapList...
2
inserting to FooMap...
inserting to fooMapList...
3
inserting to FooMap...
inserting to fooMapList...
4
inserting to FooMap...
inserting to fooMapList...
5
inserting to FooMap...
inserting to fooMapList...
You can throw away your do-nothing map classes, stop using pointers, and just
#include <iostream>
#include <utility>
#include <stdint.h>
#include <cstdlib>
#include <map>
class Foo
{
private:
int m_foobar;
public:
Foo(int value) : m_foobar(value) { }
void setfoobar(int value) { m_foobar = value; }
int getfoobar() const { return m_foobar; }
// or more simply
// int foobar;
};
using FooMap = std::map<int, Foo>;
using FooMapMap = std::map<int, FooMap>;
int main() {
FooMapMap foos;
for (auto i=1; i<=5; i++)
{
foos[i][i] = Foo(i);
}
return 0;
}
Do note that the inner map is totally pointless at this stage, as they only ever have one entry
Except if you have a really good reason to do so, avoid to obfuscate things a la Java like this and try to leverage the STL anyway you can. To that end you can use type aliases
using FooMap = std::map<int, Foo*>; // Maybe use a smart pointer instead here?
using FooMapList = std::map<int, FooMap>; // Maybe List is not an appropriate name for a map
Now, you have a Foo element you just created and want to insert it in your map list, to do so you need a way to select in which map in the list you want to insert it. I will assume you'll insert in the first map in the list:
auto FooMap::emplace(int key, Foo* value)
{
return m_newFoo.emplace(key, value);
}
void FooMapList::insertFoo(Foo* newFooObj)
{
// If the map for `getfoobar` does not exist yet, operator[] will create it
auto& mapPtr = m_fooMapList[newFooObj->getfoobar()];
if (nullptr == mapPtr)
mapPtr = new FooMap();
mapPtr->emplace(
newFooObj->getfoobar(),
newFooObj
);
}
Note that I didn't handle memory cleanup. I suggest you try to use smart pointers when applicable (std::unique_ptr and std::shared_ptr)
I have considered valid points from each of the answers to remove pointers and remove useless double level map representations. But the real world abstraction is a much complex problem which involves thousands of objects on the fly which needs to be created and destroyed dynamically. Using pointers seemed a valid approach, but JeJo' approach seemed much better.
I tried to re-use his attempt but with object pointers and the below seems to work. With the below insert functions
In the FooMap class the function would be
void FooMap::insertFoo(Foo* newFooObj)
{
m_newFoo.emplace(newFooObj->getfoobar(), newFooObj);
}
const std::map<int, Foo*> FooMap::getList()
{
return m_newFoo;
}
and in FooMapList it would be
void FooMapList::insertFooList(Foo* newFooObj)
{
std::map <int, FooMap*>::iterator iter;
FooMap *localFooMap = NULL;
iter = m_fooMapList.find( newFooObj->getfoobar() );
if( iter == m_fooMapList.end() )
{
localFooMap = new FooMap;
localFooMap->insertFoo(newFooObj);
m_fooMapList.emplace(newFooObj->getfoobar(), localFooMap );
}
else
{
localFooMap = iter->second;
localFooMap->insertFoo(newFooObj);
m_fooMapList.emplace(newFooObj->getfoobar(), localFooMap );
}
}
const std::map<int, FooMap*> FooMapList::getList()
{
return m_fooMapList;
}
I would appreciate feedback for this approach too. I will be adding the calls to destructor to clean up the created objects

Constructor to add every instance of a class to a list object

New to c++ and OOP. I'm trying to figure out lists and iteration, so I've created the following example code. I create a couple Thing objects, but I want to make sure that when a Thing is created, its constructor adds it to a list "things" (inside the lists object) so that I can keep track of every instance of Thing. At the bottom of main() I then iterate through the list of Things. Is there a better way to do this, or could you point out how to do this in my Thing constructor? Thanks!!
#include <iostream>
#include <list>
class Thing;
class Lists
{
public:
std::list<Thing> things;
Lists() {
std::cout << "List object with list 'things' created" << std::endl;
}
};
class Thing
{
public:
int howMuch, pointer;
Thing(int x, Lists* y)
{
howMuch = x;
y->things.push_back(this);
}
};
int main()
{
//create the object that holds the list of things
Lists lists;
//make some objects, and pass a pointer of the lists to the constructor
Thing thingA(123, &lists);
Thing thingB(456, &lists);
for (std::list<Thing>::iterator it = lists.things.begin(); it != lists.things.end(); ++it)
std::cout << "test" << it->howMuch << std::endl;
return 0;
}
You can store created items inside the Thing class itself using a static field _things:
#include <iostream>
#include <list>
class Thing
{
static std::list<Thing> _things;
public:
int howMuch, pointer;
Thing(int x) : howMuch(x)
{
_things.push_back(*this);
}
static std::list<Thing> getAllThings()
{
return _things;
}
};
std::list<Thing> Thing::_things;
int main()
{
Thing thingA(123);
Thing thingB(456);
auto allThings = Thing::getAllThings();
for (auto it = allThings.begin(); it != allThings.end(); ++it)
std::cout << "test " << it->howMuch << std::endl;
return 0;
}
The original example and the example in answer 1 encounter problems as soon as any Thing is destroyed (as François Andrieux mentioned), even if you use a pointer to Thing in the list. If you use a Thing in a subroutine as a local variable, the Thing is destroyed at the end of this function, but is still in the list. To solve this problem, you have to remove the Thing from the list in the destructor of Thing. But if you do so, you get a problem, when Thing is a global object. You have two global objects - the list and the Thing. It is not clear, which is destroyed first, so you can end up whith an access violation, which is difficult to debug, because it happens after exit().
Here is my proposal:
template<class T>
class InstanceIterator{ // Iterator for an InstanceList
public:
InstanceIterator(T*pT)
: pt(pT)
{}
T& operator*(){ return *pt; }
T* operator->(){ return pt; }
InstanceIterator operator++(){
pt=pt->instanceList.pNext;
return *this;
}
int operator!=(const InstanceIterator<T>& i){ return i.pt!=pt; }
private:
T*pt;
};
template<class T>
class InstanceList{
// this class means not the whole list, but only the element (pNext)
// which is inserted into the object you want to have in a list.
// there is no explizite list, every instance class T has a part of the list
public:
InstanceList(){};
void insert(T* pt){ // gets the this-pointer of the surrounding class
pNext=pFirst;
pFirst=pt;
}
~InstanceList();
static InstanceIterator<T> begin(){ return pFirst; }
static InstanceIterator<T> end(){ return 0; }
static bool empty(){ return pFirst==0; }
private:
InstanceList(const InstanceList&);// no copy constructor
void operator=(const InstanceList&);// no assignment
static T* pFirst;
T* pNext;
friend class InstanceIterator<T>;
};
template<class T>
InstanceList<T>::~InstanceList(){
T**ppInst=&pFirst;
// search for myself
while(&((*ppInst)->instanceList)!=this) { // its me?
if(0==(*ppInst)) {
return; // emergency exit
}
ppInst=&((*ppInst)->instanceList.pNext); // the next please
}
// and remove me from the list
(*ppInst)=pNext;
}
template<class T>
T* InstanceList<T>::pFirst=0;
// how to use and test the above template:
// (uses 3 objects: one is global, one is local,
// and one is deleted before going through the list)
class InstanceTest { // example class, the instances of this class are listed
public:
InstanceTest(int i)
: i(i)
{
instanceList.insert(this); // dont forget this line
}
InstanceList<InstanceTest> instanceList; // must have this line with exact this name
int i;
};
InstanceTest t1(1); // a global object
int main() {
std::cout << "testing InstanceIterator";
InstanceTest t2(2); // a local object
InstanceTest* pt3 = new InstanceTest(3); // will be deleted later
int sum(0);
for(InstanceIterator<InstanceTest> it= InstanceList<InstanceTest>::begin(); it!= InstanceList<InstanceTest>::end();++it){
sum += it->i;
}
int testFailed(0);
if (sum != 6) testFailed++;
delete pt3;
sum = 0;
for (InstanceIterator<InstanceTest> it = InstanceList<InstanceTest>::begin(); it != InstanceList<InstanceTest>::end(); ++it) {
sum += it->i;
}
if (sum != 3) testFailed++;
if (testFailed) {
std::cout << "... FAILED !!!\n";
}
else std::cout << "... OK\n";
return testFailed;
}

Object storing a non-owning reference that must be informed before the reference is destructed

I have a class following this pattern:
class Foo
{
public:
// Create a Foo whose value is absolute
Foo(int x) : other_(0), a_(x) {}
// Create a Foo whose value is relative to another Foo
Foo(Foo * other, int dx) : other_(other), a_(dx) {}
// Get the value
double x() const
{
if(other_)
return other_->x() + a_;
else
return a_;
}
private:
Foo * other_;
int a_;
};
The Foo objects are all owned by a Bar:
class Bar
{
public:
~Bar() { for(int i=0; i<foos_.size(); i++) delete foos_[i]; }
private:
vector<Foo*> foos_;
};
Of course, this is a simplified example to get the idea. I have a guarantee that there are no loop of Foos, and that linked Foos all belong to the same instance of Bar. So far, so good. To do things the C++11 way, I would use vector< unique_ptr<Foo> > foos_; in Bar, and pass foos_[i].get() as potential argument of a Foo constructor.
There is the deal:
This a GUI application, and the user can interactively delete some Foo at will. The expected behaviour is that if foo1 is deleted, and foo2 is relative to foo1, then foo2 becomes now "absolute":
void Foo::convertToAbsolute() { a_ += other_->x(); other_ = 0; }
void usageScenario()
{
Foo * foo1 = new Foo(42);
Foo * foo2 = new Foo(foo1, 42);
// Here, foo1->x() = 42 and foo2->x() = 84
foo1->setX(10);
// Here, foo1->x() = 10 and foo2->x() = 52
delete foo1;
// Here, foo2->x() = 52
}
I know it is possible to do it using raw pointers, by using a a DAG structure with back-pointers, so the Foo are aware of who "depends on them", and can inform them before deletion (possible solutions detailed here and here ).
My question is: Would you handle it the same way? Is there a way using standard C++11 smart pointers to avoid having the explicit back-pointers, and then avoid explicitely calling areRelativeToMe_[i]->convertToAbsolute(); in the destructor of Foo? I was thinking about weak_ptr, something in the spirit of:
class Foo { /* ... */ weak_ptr<Foo> other_; };
double Foo::x() const
{
if(other_.isExpired())
convertToAbsolute();
// ...
}
But the issue is that convertToAbsolute() needs the relative Foo to still exist. So I need a non-owning smart-pointer that can tell "this reference is logically expired", but actually extends the lifetime of the referenced object, until it is not needed.
It could be seen either like a weak_ptr extending the lifetime until it is not shared with any other weak_ptr:
class Foo { /* ... */ extended_weak_ptr<Foo> other_; };
double Foo::x() const
{
if(other_.isExpired())
{
convertToAbsolute();
other_.reset(); // now the object is destructed, unless other
// foos still have to release it
}
// ...
}
Or like a shared_ptr with different level of ownership:
class Bar { /* ... */ vector< multilevel_shared_ptr<Foo> foos_; };
class Foo { /* ... */ multilevel_shared_ptr<Foo> other_; };
void Bar::createFoos()
{
// Bar owns the Foo* with the highest level of ownership "Level1"
// Creating an absolute Foo
foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(42), Level1) );
// Creating a relative Foo
foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(foos_[0],7), Level1) );
}
Foo::Foo(const multilevel_unique_ptr<Foo> & other, int dx) :
other_( other, Level2 ),
// Foo owns the Foo* with the lowest level of ownership "Level2"
a_(dx)
{
}
double Foo::x() const
{
if(other_.noLevel1Owner()) // returns true if not shared
// with any Level1 owner
{
convertToAbsolute();
other_.reset(); // now the object is destructed, unless
// shared with other Level2 owners
}
// ...
}
Any thoughts?
All Foo are owned by Bar. Therefore all deletions of Foo happen in Bar methods. So I might implement this logic inside Bar:
void Bar::remove(Foo* f)
{
using namespace std::placeholders;
assert(std::any_of(begin(foos_), end(foos_),
std::bind(std::equal_to<decltype(f)>(), f, _1));
auto const& children = /* some code which determines which other Foo depend on f */;
std::for_each(begin(children), end(children),
std::mem_fn(&Foo::convertToAbsolute));
foos_.remove(f);
delete f; // not needed if using smart ptrs
}
This would ensure that the expiring Foo still exists when convertToAbsolute is called on its dependents.
The choice of how to compute children is up to you. I would probably have each Foo keep track of its own children (cyclic non-owning pointers), but you could also keep track of it inside Bar, or search through foos_ on demand to recompute it when needed.
You can use the double link approach even with more than one other dependent object. You only have to link together the dependents of the same object:
class Foo {
public:
explicit Foo(double x)
: v(x), foot(nullptr), next(nullptr), dept(nullptr) {}
// construct as relative object; complexity O(1)
Foo(Foo*f, double x)
: v(x), foot(f), dept(nullptr)
{ foot->add_dept(this); }
// destruct; complexity O(n_dept) + O(foot->n_dept)
// O(1) if !destroy_carefully
~Foo()
{
if(destroy_carefully) {
for(Foo*p=dept; p;) {
Foo*n=p->next;
p->unroot();
p=n;
}
if(foot) foot->remove_dept(this);
}
}
double x() const
{ return foot? foot->x() + v : v; }
private:
double v; // my position relative to foot if non-null
Foo*foot; // my foot point
Foo*next; // next object with same foot point as me
Foo*dept; // first object with me as foot point
// change to un-rooted; complexity: O(1)
void unroot()
{ v+=foot->x(); foot=nullptr; next=nullptr; }
// add d to the linked list of dependents; complexity O(1)
void add_dept(const Foo*d)
{ d->next=dept; dept=d; }
// remove d from the linked list of dependents ; complexity O(n_dept)
void remove_dept(const Foo*d)
{
for(Foo*p=dept; p; p=p->next)
if(p==d) { p=d->next; break; }
}
static bool destroy_carefully;
};
bool Foo::destroy_carefully = true;
Here, setting Foo::destroy_carefully=false allows you to delete all remaining objects without going through the untangling of mutual references (which can be expensive).
Interesting problem. I guess you figured that you can add a pointer to the 'child' object. I am not sure, whether smart pointers help here. I tried to implement the code below using std::weak_ptr<Foo> but you can only use it for other_ and not for the listener.
Another thought I had was to leave the responsibility to some higher power. The problem that you have is that you would like to do the update when the destructor is called. Perhaps better approach would be to call convertToAbsolute() from somewhere else. For example, if you are storing the Foos in a vector and the user clicks delete in the UI, you need the index of the object in order to delete so might as well update the adjacent item to absolute value.
Below is a solution that uses a Foo*.
#include <iostream>
#include <memory>
#include <vector>
class Foo
{
public:
// Create a Foo whose value is absolute
Foo(int x) : other_(nullptr), listener_(nullptr), a_(x)
{}
// Create a Foo whose value is relative to another Foo
Foo(Foo* other, int dx) :
other_(other), listener_(nullptr), a_(dx)
{
other->setListener(this);
}
~Foo()
{
convertToAbsolute();
if (listener_)
listener_->other_ = nullptr;
}
// Get the value
double x() const
{
if(other_)
return other_->x() + a_;
else
return a_;
}
void setX(int i)
{
a_ = i;
}
void convertToAbsolute()
{
if (listener_)
listener_->a_ += a_;
}
void setListener(Foo* listener)
{
listener_ = listener;
}
private:
Foo* other_;
Foo* listener_;
int a_;
};
void printFoos(const std::vector<std::shared_ptr<Foo>>& foos)
{
std::cout << "Printing foos:\n";
for(const auto& f : foos)
std::cout << '\t' << f->x() << '\n';
}
int main(int argc, const char** argv)
{
std::vector<std::shared_ptr<Foo>> foos;
try
{
auto foo1 = std::make_shared<Foo>(42);
auto foo2 = std::make_shared<Foo>(foo1.get(), 42);
foos.emplace_back(foo1);
foos.emplace_back(foo2);
}
catch (std::exception& e)
{
std::cerr << e.what() << '\n';
}
// Here, foo1->x() = 42 and foo2->x() = 84
printFoos(foos);
foos[0]->setX(10);
// Here, foo1->x() = 10 and foo2->x() = 52
printFoos(foos);
foos.erase(foos.begin());
// Here, foo2->x() = 52
printFoos(foos);
return 0;
}
If you have a Signal/Slot framework, that provides a nice place to do the unlinking. For example, using the Qt libraries these classes could look like:
class Foo : public QObject
{
Q_OBJECT
public:
// Create a Foo whose value is absolute
Foo(int x) : QObject(nullptr), other_(nullptr), a_(x) {}
// Create a Foo whose value is relative to another Foo
Foo(Foo * other, int dx) : QObject(nullptr) other_(other), a_(dx) {
connect(other, SIGNAL(foo_dying()), this, SLOT(make_absolute()));
}
~Foo() { emit foo_dying(); }
// Get the value
double x() const
{
if(other_)
return other_->x() + a_;
else
return a_;
}
signals:
void foo_dying();
private slots:
void make_absolute()
{
a_ += other_->x();
other_ = nullptr;
}
private:
Foo * other_;
int a_;
};
Here is probably the simplest way to achieve the goal using back-pointers. You can use the container you want depending on your complexity requirements (e.g., a set, hash table, vector, linked list, etc.). A more involved but more efficient approach is proposed by Walter.
class Foo
{
public:
// Create a Foo whose value is absolute
Foo(int x) : other_(0), a_(x) {}
// Create a Foo whose value is relative to another Foo
Foo(Foo * other, int dx) : other_(other), a_(dx)
{
other->areRelativeToMe_.insert(this);
}
// Get the value
double x() const
{
if(other_)
return other_->x() + a_;
else
return a_;
}
// delete the Foo
Foo::~Foo()
{
// Inform the one I depend on, if any, that I'm getting destroyed
if(other_)
other_->areRelativeToMe_.remove(this);
// Inform people that depends on me that I'm getting destructed
for(int i=0; i<areRelativeToMe_.size(); i++)
areRelativeToMe_[i]->convertToAbsolute();
}
private:
Foo * other_;
int a_;
Container<Foo*> areRelativeToMe_; // must provide insert(Foo*)
// and remove(Foo*)
// Convert to absolute
void convertToAbsolute()
{
a_ += other_->x();
other_ = 0;
}
};

Fixing C++ legacy code: class Iterator

As part of an assignment for a data structures class, I am trying to get this over a decade-old code to actually work. The code is found here: http://www.brpreiss.com/books/opus4/
(And to all of the users here who are horrified at such bad design, take heart - this is a homework assignment where the goal is ostensibly to get someone else's code to work. I am not advocating its use.)
Here, the author defined the class Stack and its associated Iterator:
#ifndef STACK_H
#define STACK_H
#include "linkList.h"
#include "container.h"
class Stack : public virtual Container
{
public:
virtual Object& Top () const = 0;
virtual void Push (Object&) = 0;
virtual Object& Pop () = 0;
};
class StackAsLinkedList : public Stack
{
LinkedList<Object*> list;
class Iter;
public:
StackAsLinkedList () : list() {}
~StackAsLinkedList() { Purge(); }
//
// Push, Pop and Top
//
void Push(Object& object);
Object& Pop() override;
Object& Top() const override;
int CompareTo(Object const& obj) const;
//
// purge elements from, and accept elements onto, the list
//
void Purge();
void Accept (Visitor&) const;
friend class Iter;
};
class StackAsLinkedList::Iter : public Iterator
{
StackAsLinkedList const& stack;
ListElement<Object*> const* position;
public:
Iter (StackAsLinkedList const& _stack) : stack(_stack) { Reset(); }
//
// determine whether iterator is pointing at null
//
bool IsDone() const { return position == 0; }
//
// overloaded dereference and increment operator
//
Object& operator*() const;
void operator++();
void Reset() { position = stack.list.Head(); }
};
#endif
I am not sure what the objective is here, because trying to instantiate a StackAsLinkedList::Iter will predictably give an error because it is private. Furthermore, the author doesn't use the iterator he just implemented for stack in the below example, which instead uses the iterator defined in the parent class of Stack called Container to traverse the stack and print the values:
StackAsLinkedList stack;
Iter& i = stack.NewIterator();
stack.Push(*new Int(1) ); //type "Int" is a Wrapper for primitive "int"
stack.Push(*new Int(2) );
...
while ( ! outIter.IsDone() )
{
cout << *outIter << endl;
++outIter;
}
...
But when he creates stack.NewIterator(), a look at the method call in Container shows:
virtual Iterator& NewIterator () const { return *new NullIterator (); }
So the conditional in the while statement will always fail and thus the body will never execute.
This leads me to believe that I should be implementing another NewIterator method for Stack, but I am not sure what the return value should be ( *new StackAsLinkedList::Iter(_stack) ?).
Any ideas?
Adding the following method in StackAsLinkedList seemed to clear up the problem:
Iterator& StackAsLinkedList::NewIterator() const
{
return *new Iter(*this);
}
Also, the order of assignment in main() was also an issue. This seemed to correct it:
StackAsLinkedList stack;
stack.Push(*new Int(1) ); //type "Int" is a Wrapper for primitive "int"
stack.Push(*new Int(2) );
...
Iter& i = stack.NewIterator();
while ( ! outIter.IsDone() )
{
cout << *outIter << endl;
++outIter;
}
I realize that this solution is not ideal - ideally I should refactor or better yet just start over (or just use STL). But as I said above, the goal was to just get this stuff to compile and work within a limited time-frame. So to echo what others have said: please don't use this code!

is back_insert_iterator<> safe to be passed by value?

I have a code that looks something like:
struct Data { int value; };
class A {
public:
typedef std::deque<boost::shared_ptr<Data> > TList;
std::back_insert_iterator<TList> GetInserter()
{
return std::back_inserter(m_List);
}
private:
TList m_List;
};
class AA {
boost::scoped_ptr<A> m_a;
public:
AA() : m_a(new A()) {}
std::back_insert_iterator<A::TList> GetDataInserter()
{
return m_a->GetInserter();
}
};
class B {
template<class OutIt>
CopyInterestingDataTo(OutIt outIt)
{
// loop and check conditions for interesting data
// for every `it` in a Container<Data*>
// create a copy and store it
for( ... it = ..; .. ; ..) if (...) {
*outIt = OutIt::container_type::value_type(new Data(**it));
outIt++; // dummy
}
}
void func()
{
AA aa;
CopyInterestingDataTo(aa.GetDataInserter());
// aa.m_a->m_List is empty!
}
};
The problem is that A::m_List is always empty even after CopyInterestingDataTo() is called. However, if I debug and step into CopyInterestingDataTo(), the iterator does store the supposedly inserted data!
update:
I found the culprit. I actually have something like:
class AA {
boost::scoped_ptr<A> m_a;
std::back_insert_iterator<A::TList> GetDataInserter()
{
//return m_a->GetInserter(); // wrong
return m_A->GetInserter(); // this is the one I actually want
}
// ..... somewhere at the end of the file
boost::scoped_ptr<A> m_A;
};
Now, which answer should I mark as answer?
Really sorry for those not chosen, but you guys definitely got some up-votes : )
The short answer is yes, back_insert_iterator is safe to pass by value. The long answer: From standard 24.4.2/3:
Insert iterators satisfy the
requirements of output iterators.
And 24.1.2/1
A class or a built-in type X satisfies
the requirements of an output iterator
if X is an Assignable type (23.1) ...
And finally from Table 64 in 23.1:
expression t = u
return-type T&
post-condition t is equivalent to u
EDIT: At a glance your code looks OK to me, are you 100% certain that elements are actually being inserted? If you are I would single step through the code and check the address of the aa.m_a->m_List object and compare it to the one stored in outIt in CopyInterestingDataTo, if they're not the same something's fishy.
The following code, which compiles, prints "1", indicating one item added to the list:
#include <iostream>
#include <deque>
#include "boost/shared_ptr.hpp"
#include "boost/scoped_ptr.hpp"
struct Data {
int value;
Data( int n ) : value(n) {}
};
struct A {
typedef std::deque<boost::shared_ptr<Data> > TList;
std::back_insert_iterator<TList> GetInserter()
{
return std::back_inserter(m_List);
}
TList m_List;
};
struct AA {
boost::scoped_ptr<A> m_a;
AA() : m_a(new A()) {}
std::back_insert_iterator<A::TList> GetDataInserter()
{
return m_a->GetInserter();
}
};
struct B {
template<class OutIt>
void CopyInterestingDataTo(OutIt outIt)
{
*outIt = typename OutIt::container_type::value_type(new Data(0));
outIt++; // dummy
}
int func()
{
AA aa;
CopyInterestingDataTo(aa.GetDataInserter());
return aa.m_a->m_List.size();
}
};
int main() {
B b;
int n = b.func();
std::cout << n << std::endl;
}