Get a C++ set to contain objects

Discussion in 'C++' started by janzon@gmail.com, Sep 30, 2006.

  1. Guest

    Hi!

    I'm a Java guy, forced to do some C++. I want to add objects to the set
    container. I don't even get past the compilation step (which is a good
    thing in a way). For instance, why doesn't the following code compile?

    #include <iostream>
    #include <set>

    using namespace std;

    class myClass {
    public:
    void hello() { cout << "hello"; }
    };

    int main() {
    myClass mc;

    set<myClass> s;
    s.insert(mc); // If this line is commented away, no error
    }


    The compiles gives as a reason the following:

    bik> CC -o prog4 prog4.cc
    "/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
    operation "const myClass<const myClass" is illegal.
    "/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
    While instantiating "std::less<myClass>::eek:perator()(const myClass&,
    const myClass&) const".
    "/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
    Instantiated from __rwstd::__rb_tree<myClass, myClass,
    __rwstd::__ident<myClass, myClass>, std::less<myClass>,
    std::allocator<myClass>>::insert(const myClass&).
    "/opt/SUNWspro/prod/include/CC/Cstd/./set", line 224: Where:
    Instantiated from non-template code.
    1 Error(s) detected.
    , Sep 30, 2006
    #1
    1. Advertising

  2. Kai-Uwe Bux Guest

    wrote:

    > Hi!
    >
    > I'm a Java guy, forced to do some C++. I want to add objects to the set
    > container. I don't even get past the compilation step (which is a good
    > thing in a way). For instance, why doesn't the following code compile?
    >
    > #include <iostream>
    > #include <set>
    >
    > using namespace std;
    >
    > class myClass {
    > public:
    > void hello() { cout << "hello"; }
    > };
    >
    > int main() {
    > myClass mc;
    >
    > set<myClass> s;
    > s.insert(mc); // If this line is commented away, no error
    > }

    [snip]

    The std::set<> container keeps its elements in order. For this to happen,
    you need to supply a comparison predicate. Technically, you have the
    following options:

    a) Define an operator< for myClass. This can be either a member operator or
    a freestanding friend. This solution conveys the message that the objects
    of type myClass a naturally comparable.

    b) Specialize std::less<myClass>. This indicates that the ordering you
    define is less natural and more of a hack to make things like std::set and
    std::map work.

    c) Define a freestanding comparison function

    bool some_function_name ( myClass const &, myClass const & );

    and pass it as a parameter upon construction of the set. Generally, I would
    not recommend this since you will have to supply additional template
    parameters and it makes the code less readable. This, I would use only when
    there are several sorting criteria for the same type that I need to use
    independently in the code.


    In any case, the comparison predicate you supply has to define a ordering,
    i.e., you may not have things like a < b < c < a and you should have either
    a<b or b<a or a==b. If these conditions are not met, the code is likely to
    compiler but it is also likely to give unexpected results (aka bugs).


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Sep 30, 2006
    #2
    1. Advertising

  3. wrote:

    > int main() {
    > myClass mc;
    >
    > set<myClass> s;
    > s.insert(mc); // If this line is commented away, no error
    > }


    std::set is ordered, then it needs a way to compare things (and also to
    evaluate equality). You need a < operator for objects of your class, or an
    specialization for him of the std::less template, or add to the definition
    of your set a compare operation.

    --
    Salu2
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Sep 30, 2006
    #3
  4. Daniel T. Guest

    wrote:

    > Hi!
    >
    > I'm a Java guy, forced to do some C++. I want to add objects to the set
    > container. I don't even get past the compilation step (which is a good
    > thing in a way). For instance, why doesn't the following code compile?
    >
    > #include <iostream>
    > #include <set>
    >
    > using namespace std;
    >
    > class myClass {
    > public:
    > void hello() { cout << "hello"; }
    > };
    >
    > int main() {
    > myClass mc;
    >
    > set<myClass> s;
    > s.insert(mc); // If this line is commented away, no error
    > }


    Note, although the above compiles in Java, it wouldn't work because the
    set (TreeMap in Java) has no way to compare two myClass objects to see
    what the order should be.

    > The compiles gives as a reason the following:
    >
    > bik> CC -o prog4 prog4.cc
    > "/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
    > operation "const myClass<const myClass" is illegal.
    > "/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
    > While instantiating "std::less<myClass>::eek:perator()(const myClass&,
    > const myClass&) const".


    The above complains about the very thing that would cause this code to
    fail in Java. No way to compare two myClass objects to determine order.

    To do that in C++, you must provide a global function that returns true
    of the left hand argument comes before the right hand argument.

    bool compare( const myClass& lhs, const myClass& rhs ) {
    // return true if lhs should come before rhs, otherwise return false.
    }

    If you name your compare function "operator<" then the set will just
    work. If you want to name it something else, then you will need to let
    set know.

    --
    There are two things that simply cannot be doubted, logic and perception.
    Doubt those, and you no longer have anyone to discuss your doubts with,
    nor any ability to discuss them.
    Daniel T., Sep 30, 2006
    #4
  5. lw1a2 Guest

    wrote:
    > Hi!
    >
    > I'm a Java guy, forced to do some C++. I want to add objects to the set
    > container. I don't even get past the compilation step (which is a good
    > thing in a way). For instance, why doesn't the following code compile?
    >
    > #include <iostream>
    > #include <set>
    >
    > using namespace std;
    >
    > class myClass {
    > public:
    > void hello() { cout << "hello"; }
    > };
    >
    > int main() {
    > myClass mc;
    >
    > set<myClass> s;
    > s.insert(mc); // If this line is commented away, no error
    > }
    >
    >
    > The compiles gives as a reason the following:
    >
    > bik> CC -o prog4 prog4.cc
    > "/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
    > operation "const myClass<const myClass" is illegal.
    > "/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
    > While instantiating "std::less<myClass>::eek:perator()(const myClass&,
    > const myClass&) const".
    > "/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
    > Instantiated from __rwstd::__rb_tree<myClass, myClass,
    > __rwstd::__ident<myClass, myClass>, std::less<myClass>,
    > std::allocator<myClass>>::insert(const myClass&).
    > "/opt/SUNWspro/prod/include/CC/Cstd/./set", line 224: Where:
    > Instantiated from non-template code.
    > 1 Error(s) detected.


    You must overload myClass's operator <
    Like this:

    #include <iostream>
    #include <set>
    using namespace std;


    class myClass {
    public:
    myClass():data(0){}
    void hello() { cout << "hello"; }
    bool operator<(const myClass& rhs) const
    {
    return data<rhs.data;
    }
    private:
    int data;//This is a comparative data.
    };


    int main() {
    myClass mc;

    set<myClass> s;
    s.insert(mc); // If this line is commented away, no error



    }
    lw1a2, Oct 1, 2006
    #5
  6. "Daniel T." <> wrote in message
    news:...
    > wrote:
    >
    >> Hi!
    >>
    >> I'm a Java guy, forced to do some C++. I want to add objects to the set
    >> container. I don't even get past the compilation step (which is a good
    >> thing in a way). For instance, why doesn't the following code compile?
    >>
    >> #include <iostream>
    >> #include <set>
    >>
    >> using namespace std;
    >>
    >> class myClass {
    >> public:
    >> void hello() { cout << "hello"; }
    >> };
    >>
    >> int main() {
    >> myClass mc;
    >>
    >> set<myClass> s;
    >> s.insert(mc); // If this line is commented away, no error
    >> }

    >
    > Note, although the above compiles in Java, it wouldn't work because the
    > set (TreeMap in Java) has no way to compare two myClass objects to see
    > what the order should be.


    TreeSet surely?

    <snip>
    Stuart Golodetz, Oct 1, 2006
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. 7stud
    Replies:
    11
    Views:
    662
    Dennis Lee Bieber
    Mar 20, 2007
  2. Replies:
    7
    Views:
    916
    James Kanze
    Mar 20, 2009
  3. Roger Pack
    Replies:
    3
    Views:
    143
    Roger Pack
    Sep 28, 2010
  4. Jason Carlton
    Replies:
    11
    Views:
    218
    Dr J R Stockton
    Dec 8, 2009
  5. Replies:
    16
    Views:
    966
Loading...

Share This Page