Adding Map Entries

Discussion in 'C++' started by cppaddict, Jul 24, 2004.

  1. cppaddict

    cppaddict Guest

    Hi,

    I have some code which uses std::map to associate cartesian POINTs
    with values. My current syntax for adding new (POINT,value) entries
    to the map is clunky -- it takes three lines for each entry. There
    must be a way to trim it down:

    <code>
    #include <map>
    #include <iostream>

    typedef struct tagPOINT { // pt
    long x;
    long y;
    } POINT;

    //map comparison fctn
    struct PointCompare {
    bool operator() (POINT p1, POINT p2) const {
    if (p1.x == p2.x)
    return p1.y < p2.y;
    else
    return p1.x < p2.x;
    }
    };


    int main() {


    std::map<POINT, int,PointCompare> testPoints;

    //THIS CODE IS HERE IS THE PROBLEM
    POINT pnt1 = {1,1};
    std::pair<POINT, int> pair1(pnt1,123);
    testPoints.insert(pair1);

    POINT pnt2 = {1,2};
    std::pair<POINT, int> pair2(pnt2,456);
    testPoints.insert(pair2);

    std::cout << "direct access {1,1} -> " << testPoints[pnt1] <<
    std::endl;

    std::map<POINT, int, PointCompare>::iterator iter;
    for (iter = testPoints.begin(); iter != testPoints.end();
    ++iter) {
    POINT iterPnt = iter->first;
    std::cout << "iterator access: iter->first = {" <<
    iterPnt.x << "," << iterPnt.y << "}" << std::endl;
    std::cout << "iterator access: iter->second = " <<
    (iter->second) << std::endl;
    }

    return 0;
    }

    </code>

    Thanks for any help,
    cpp
    cppaddict, Jul 24, 2004
    #1
    1. Advertising

  2. You can make things a bit simpler by making POINTs real objects
    and adding a constructor so you can stamp out POINT objects
    like POINT p(1,2) instead of the mechanism you are using.

    You dont have to explicitly create variables for POINT and pair,
    you can do things like this:
    testPoints.insert( std::pair<POINT,int>(POINT(1,2), 456) );

    this creates a temporary POINT object with values 1, 2 and a pair
    object with that POINT and they int value 456.

    The std::pair<POINT,int> is a bit of a mouthful, I thought you
    could just do std::pair and the compiler should deduce the template
    arguments, however you can just create a typedef to use instead if
    you don't want to type that stuff in over and over.

    I've tinkered with your original code below

    #include <std_disclaimers.h>

    #include <map>
    #include <iostream>
    struct POINT { // pt
    long x;
    long y;
    POINT(long xx, long yy)
    :x(xx), y(yy){}
    } ;

    //map comparison fctn
    struct PointCompare {
    bool operator() (POINT p1, POINT p2) const {
    if (p1.x == p2.x)
    return p1.y < p2.y;
    else
    return p1.x < p2.x;
    }
    };


    int main() {


    std::map<POINT, int,PointCompare> testPoints;





    POINT pnt2(1,2);

    testPoints.insert( std::pair<POINT,int>(POINT(1,2), 456) );
    POINT pnt1(1,2);
    std::cout << "direct access {1,1} -> " << testPoints[pnt1] <<
    std::endl;

    std::map<POINT, int, PointCompare>::iterator iter;
    for (iter = testPoints.begin(); iter != testPoints.end();
    ++iter) {
    POINT iterPnt = iter->first;
    std::cout << "iterator access: iter->first = {" <<
    iterPnt.x << "," << iterPnt.y << "}" << std::endl;
    std::cout << "iterator access: iter->second = " <<
    (iter->second) << std::endl;
    }

    return 0;
    }





    "cppaddict" <> wrote in message
    news:...
    > Hi,
    >
    > I have some code which uses std::map to associate cartesian POINTs
    > with values. My current syntax for adding new (POINT,value) entries
    > to the map is clunky -- it takes three lines for each entry. There
    > must be a way to trim it down:
    >
    > <code>
    > #include <map>
    > #include <iostream>
    >
    > typedef struct tagPOINT { // pt
    > long x;
    > long y;
    > } POINT;
    >
    > //map comparison fctn
    > struct PointCompare {
    > bool operator() (POINT p1, POINT p2) const {
    > if (p1.x == p2.x)
    > return p1.y < p2.y;
    > else
    > return p1.x < p2.x;
    > }
    > };
    >
    >
    > int main() {
    >
    >
    > std::map<POINT, int,PointCompare> testPoints;
    >
    > //THIS CODE IS HERE IS THE PROBLEM
    > POINT pnt1 = {1,1};
    > std::pair<POINT, int> pair1(pnt1,123);
    > testPoints.insert(pair1);
    >
    > POINT pnt2 = {1,2};
    > std::pair<POINT, int> pair2(pnt2,456);
    > testPoints.insert(pair2);
    >
    > std::cout << "direct access {1,1} -> " << testPoints[pnt1] <<
    > std::endl;
    >
    > std::map<POINT, int, PointCompare>::iterator iter;
    > for (iter = testPoints.begin(); iter != testPoints.end();
    > ++iter) {
    > POINT iterPnt = iter->first;
    > std::cout << "iterator access: iter->first = {" <<
    > iterPnt.x << "," << iterPnt.y << "}" << std::endl;
    > std::cout << "iterator access: iter->second = " <<
    > (iter->second) << std::endl;
    > }
    >
    > return 0;
    > }
    >
    > </code>
    >
    > Thanks for any help,
    > cpp
    Dave Townsend, Jul 24, 2004
    #2
    1. Advertising

  3. cppaddict

    Ali Cehreli Guest

    On Fri, 23 Jul 2004 16:53:58 -0700, cppaddict wrote:

    > Hi,
    >
    > I have some code which uses std::map to associate cartesian POINTs with
    > values. My current syntax for adding new (POINT,value) entries to the
    > map is clunky -- it takes three lines for each entry. There must be a
    > way to trim it down:
    >
    > <code>
    > #include <map>
    > #include <iostream>
    >
    > typedef struct tagPOINT { // pt
    > long x;
    > long y;
    > } POINT;


    You don't need the typedef trick for struct declarations in C++:

    struct tagPOINT { /* ... */ };
    or
    struct POINT { /* ... */ };

    It is convenient to define a constructor even for a simple struct so
    that the code will be more readable (see below):

    struct POINT
    {
    long x;
    long y;

    POINT(long x_arg, long y_arg)
    :
    x(x_arg),
    y(y_arg)
    {}
    };

    [...]

    > int main() {
    >
    >
    > std::map<POINT, int,PointCompare> testPoints;


    You can use typedefs to simplify the code:

    typedef std::map<POINT, int,PointCompare> Points;
    typedef Points::iterator PointIter;

    Points testPoints;

    >
    > //THIS CODE IS HERE IS THE PROBLEM
    > POINT pnt1 = {1,1};
    > std::pair<POINT, int> pair1(pnt1,123);
    > testPoints.insert(pair1);


    Now you can replace the above three lines with

    testPoints.insert(std::make_pair(POINT(1, 1), 123));

    Alternatively:

    testPoints[POINT(1, 1)] = 123;

    [...]

    > std::map<POINT, int, PointCompare>::iterator iter;
    > for (iter = testPoints.begin(); iter != testPoints.end(); ++iter)


    The typedef defined above will make this simpler too:

    for (PointIter iter = /* ... */)

    Ali
    Ali Cehreli, Jul 24, 2004
    #3
  4. cppaddict

    Ali Cehreli Guest

    On Fri, 23 Jul 2004 17:20:29 -0700, Dave Townsend wrote:

    > The std::pair<POINT,int> is a bit of a mouthful, I thought you could
    > just do std::pair and the compiler should deduce the template arguments,


    Argument deduction works only for function templates; not class
    templates.

    Some template classes have a corresponding function template to do the
    argument deduction. For example:

    template <class A>
    class Foo
    {
    public:
    Foo(A const & a);
    /* ... */
    };

    template <class A>
    Foo<A> MakeFoo(A const & a)
    {
    return Foo<A>(a);
    }

    The convenience function for std::pair is std::make_pair.

    Ali
    Ali Cehreli, Jul 24, 2004
    #4
  5. cppaddict

    cppaddict Guest

    Dave and Ali,

    Thanks for the tips.

    cpp
    cppaddict, Jul 24, 2004
    #5
  6. cppaddict

    Jerry Coffin Guest

    cppaddict <> wrote in message news:<>...
    > Hi,
    >
    > I have some code which uses std::map to associate cartesian POINTs
    > with values. My current syntax for adding new (POINT,value) entries
    > to the map is clunky -- it takes three lines for each entry. There
    > must be a way to trim it down:


    There is. Some other parts can be a bit neater as well:

    #include <map>
    #include <iostream>
    #include <iterator>
    #include <algorithm>

    class POINT {
    long x;
    long y;

    friend std::eek:stream &operator<<(std::eek:stream &os, POINT const &p) {
    return os << "{" << p.x << "," << p.y << "}";
    }
    public:
    bool operator<(POINT const &p2) const {
    if (x == p2.x)
    return y < p2.y;
    else
    return x < p2.x;
    }

    POINT(long x_init, long y_init) : x(x_init), y(y_init) {}
    };

    typedef std::pair<POINT, int> pp;

    std::eek:stream &operator<<(std::eek:stream &os, pp const &p) {
    return os << "point " << p.first << " -> " << p.second;
    }

    int main() {
    std::map<POINT, int> testPoints;

    testPoints[POINT(1,1)] = 123;
    testPoints[POINT(1,2)] = 456;

    std::cout << "point {1,1} -> " << testPoints[POINT(1,1)]
    << " (direct access)\n";
    std::copy(testPoints.begin(), testPoints.end(),
    std::eek:stream_iterator<pp>(std::cout, " (algorithm)\n"));

    return 0;
    }
    Jerry Coffin, Jul 24, 2004
    #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. Rhino

    Adding/deleting Jar entries?

    Rhino, Feb 4, 2005, in forum: Java
    Replies:
    4
    Views:
    16,508
    Rhino
    Feb 4, 2005
  2. Idelso Quintero
    Replies:
    1
    Views:
    375
    John Harrison
    Oct 1, 2004
  3. suresh
    Replies:
    4
    Views:
    280
    Richard Herring
    Dec 13, 2007
  4. Don Bruder
    Replies:
    3
    Views:
    964
    spikeysnack
    Aug 3, 2010
  5. mast4as
    Replies:
    4
    Views:
    329
    Jonathan Lee
    Aug 12, 2010
Loading...

Share This Page