-1

I'm having a problem with inheriting from STL set (i think):

Here is class Prime:

class Prime : public set<A> {
private:
  // private data members.
public:
  // C'tor...
  void printParticularA(const int& id);
}

Here is class A:

class A : public List<B>{  
private:  
  // data members.  
  int id;
public:  
  // C'tor  
  A(const A& copy) : List<B>(copy), //copy data members  
     { // validate data and throw exceptions if needed. };

  bool operator< (const A& rhs) const{  
    return id < rhs.id;  
  }

  void printReport() const {  
    for(const B& item : *this){ item.print(); }
  }

}

now here is the problem. in the next function i want to print a particular A object in the set:

void Prime::printParticularA(const int& id) {
  find(AFinder(id))->printReport();
}

i also tried this:

void Prime::printParticularA(const int& id) {
  *(find(AFinder(id))).printReport();
}

note: assume that class B has print() method.
note2: AFinder is a class for making dummy A objects using only the id data.

the problem is that when 'find' finds the objects it returns const_iterator (because every object in set is const), and when i dereference it i get a copy of the object (??) but the list of B inside it is empty!
this happens also for the '->' version.

now i know that set doesn't allow me to change the objects but i do not intend to change the object (as you can see in the declaration of printReport member function).

i appreciate any help in this!

EDIT: thanks everyone, you have helped me a lot especially learning what not to do.
I solved the problem and it wasn't in set, list nor any of my classes presented here.
my mistake was in understanding the question i was given (yes this is my homework assignment, i'm still new to c++).
sorry if you feel i have wasted your time.
i hope that i can learn from all of your experience and someday help others!
in short, THANKS!! :)

bergerg
  • 985
  • 9
  • 23
  • 7
    inheriting from STL containers is a BAD idea: http://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate – Anycorn Jun 22 '13 at 15:18
  • 3
    The standard containers were not designed for public inheritance. – Some programmer dude Jun 22 '13 at 15:19
  • 1
    Are you sure the `find()` succeeds? You should always check the return value and only dereference it if it's `!= end()`. – Angew is no longer proud of SO Jun 22 '13 at 15:22
  • i'm sure that find() succeeds. i've checked the return value (despite what is written above). @Anycorn assuming i have dealt with the 'delete' problems mentioned in the link, why is this code not working? find() returns an A object (for sure) but its list is empty.. BTW list isn't STL, it's my implementation of a list container. – bergerg Jun 22 '13 at 15:31

3 Answers3

1

Your code is pretty much messed up all around. And the problem does not look tied directly to set or iterator, but general bad things done.

For starters make your op< const and delete the copy ctor for good -- the stock one shall work fine. Use internal find of set to search and look if it found an item.

All that will likely make your described problem gone, if not, post a complete compileable example with proper text of what you see and what you expect.

Balog Pal
  • 16,195
  • 2
  • 23
  • 37
  • this is my bad, but i didn't write all the code here. the op< is const in my code and the copy c'tor validates the data copied (in the body of the method) and throws exceptions if something is wrong (so the stock one isn't good enough). and the find() method is set internal find. – bergerg Jun 22 '13 at 15:41
  • why on earth you validate data in a copy ctor? It just creates a copy of the input, and if that was invalid, you should have thrown when it got that way, earlier. – Balog Pal Jun 22 '13 at 15:54
  • still, the copy c'tor is not the problem here. even if i use the default one, i keep having this problem. – bergerg Jun 22 '13 at 16:02
1

Although you haven't included the implementation of List the problem is likely there. To be more precise the begin() and end() member functions of List may be broken. Chances are the values they return are identical (or invalid) resulting in the range based for loop doing nothing. This of course is based on your set::find is returning a valid iterator and not the end iterator.

The following example is a modification of the code in your question. It uses std::list instead of List and doesn't use AFinder since you haven't included the code for it.

#include <set>
#include <list>
#include <iostream>

struct B
{
    int id_;
    explicit B(int id) : id_(id) {}
    void print() const
    {
        std::cout << "B::id = " << id_ << std::endl;
    }
};

class A : public std::list<B>
{
public:
    explicit A(int id) : id_(id) {}

    bool operator<(const A& rhs) const
    {
        return id_ < rhs.id_;
    }

    bool operator==(const A& other) const
    {
        return id_ == other.id_;
    }

    void printReport() const
    {  
        for(auto& item : *this)
        {
            item.print();
        }
    }

private:  

    // data members.  
    int id_;

};


class Prime : public std::set<A>
{
public:

    void printParticularA(const int& id)
    {
        std::cout << "finding " << id << std::endl;
        auto el = find(A(id));
        if(el == cend())
        {
            std::cout << "not found" << std::endl;
        }
        else
        {
            find(A(id))->printReport();
        }
        std::cout << "done finding " << id << std::endl;
    }
};


int main()
{
    Prime p;

    A   a1(1);
    a1.push_back(B(1));
    a1.push_back(B(2));
    a1.push_back(B(3));
    p.insert(a1);

    A   a2(2);
    a2.push_back(B(4));
    a2.push_back(B(5));
    a2.push_back(B(6));
    p.insert(a2);

    p.printParticularA(1);

    p.printParticularA(2);

    // doesn't exit
    p.printParticularA(3);
}

This produces the following output.

finding 1
B::id = 1
B::id = 2
B::id = 3
done finding 1
finding 2
B::id = 4
B::id = 5
B::id = 6
done finding 2
finding 3
not found
done finding 3

Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
1

Your code really violate many rules of C++. Why don't you try smth like this:

#include <iostream>
#include <list>
#include <map>

using namespace std;

class SimpleInt {
public:  
  int data_;

  SimpleInt(const int data): data_(data) {};
  void print() const {cout << data_ << " ";};
};

template <typename T>
class A {  
private:  
  // private data members.  
public:  
  list<T> list_of_B_; // this is for simlicity. Make getters as you need
  const int id_; // delete it or copy to map. You sholdn't change it.

  A(int id) : list_of_B_(), id_(id) {} 
  A(const A<T>& copy) : list_of_B_(copy.list_of_B_), id_(copy.id_) {} //copy data members  
  A(A<T>&& copy) : list_of_B_(::std::move(copy.list_of_B_)), id_(copy.id_) {} //move data members  

  void printReport() const {  
    for(const T& item : list_of_B_){ item.print(); }
  }

};

template <typename T>
class Prime {
private:
  // private data members.
public:
  // The main difference with your source
  map<int, T> map_of_A_; // this is for simlicity. Make getters as you need
  // C'tor...
  void printParticularA(const int& id) {
    auto it = map_of_A_.find(id);
    if (it != map_of_A_.end())
      it->second.printReport();
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  typedef A<SimpleInt> ASimpled;
  Prime<ASimpled> prime;
  ASimpled a(1);
  a.list_of_B_.push_back(SimleInt(1));
  a.list_of_B_.push_back(SimleInt(2));
  a.list_of_B_.push_back(SimleInt(3));
  ASimpled b(2);
  b.list_of_B_.push_back(SimleInt(10));
  b.list_of_B_.push_back(SimleInt(20));
  b.list_of_B_.push_back(SimleInt(30));
  prime.map_of_A_.insert(make_pair(a.id_, a));
  prime.map_of_A_.insert(make_pair(b.id_, b));

  prime.printParticularA(2);

return 0;
}
kdmitry
  • 11
  • 1
  • 1
  • i would be happy if you told me what rules i broke just so i don't break them again... – bergerg Jun 22 '13 at 17:15
  • You already have been told about inheritance from std containers. – kdmitry Jun 22 '13 at 17:21
  • I look at your code again. Your problem in ctor of A - you don't copy your id. So after inserting to Prime your data is copied and id broked. Then find return end() which you don't test. You try to dereference end() and get your exception. But please send this code to trash anyway. – kdmitry Jun 22 '13 at 17:46
  • ...and `_tmain()` violates which part of the standard? It's in $3.6.1 – Captain Obvlious Jun 22 '13 at 18:01
  • I'm lazy to change it in project write'n'forget. May I? – kdmitry Jun 22 '13 at 18:21