Questions about new range for

Discussion in 'C++' started by Adrian, Oct 5, 2011.

  1. Adrian

    Adrian Guest

    Hi all,

    I am trying out the new range for and I have some questions when it is
    being used as a map.

    I see the standard says (6.5.4) that range-based for is equivalent to
    {
    auto && __range = range-init;
    for ( auto __begin = begin-expr,
    __end = end-expr;
    __begin != __end;
    ++__begin ) {
    for-range-declaration = *__begin;
    statement
    }
    }

    So for a std::map I think the second _RangeT is a class type - is the
    section that applies and it calls begin() and end() on my may - but the
    example I tried with an iterator doesnt work.

    My other general question is - Are the other examples correct/bad
    style/work by luck etc. I dont understand how range-based for works with
    a map.

    Any help/discussion is appreciated.

    Thanks

    Adrian Cornish

    #include <iostream>
    #include <map>

    int main(int argc, char *argv[])
    {
    typedef std::map<int, std::string> Map;
    Map arr={{9, "nine"}, {8,"eight"}, {7,"seven"}, {6, "six"}, {5,
    "five"}};

    // Test1
    for(std::pair<int, std::string> i : arr)
    {
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    // same as Test1 I believe
    // Test2
    for(Map::value_type i : arr)
    {
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    // Test3
    //error: invalid initialization of reference of type
    // 'std::pair<int, std::basic_string<char> >&' from expression of type
    // 'std::pair<const int, std::basic_string<char> >'
    //
    // for(std::pair<int, std::string> &i : arr)
    // {
    // std::cout << i.first << ' ' << i.second << ',';
    // }
    // std::cout << std::endl;

    // Test4
    // Maybe this is not the same as Test3 - since the above will not
    compile
    for(Map::value_type &i : arr)
    {
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    // Test5
    for(const Map::value_type &i : arr)
    {
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    // And this works but the not const reference of std::pair does not
    // Test6
    for(const std::pair<int, std::string> i : arr)
    {
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    // Test7
    // I really dont get why an iterator does not work? And what does it
    mean by
    // non-scalar type
    // error: conversion from 'std::pair<const int, std::basic_string<char> >'
    // to non-scalar type 'std::map<int, std::basic_string<char>
    >::const_iterator

    // {aka std::_Rb_tree_const_iterator<std::pair<const int,
    // std::basic_string<char> > >}' requested
    // for(Map::const_iterator i : arr)
    // {
    // std::cout << i->first << ' ' << i->second << ',';
    // }
    // std::cout << std::endl;

    // Test8
    for(auto i : arr)
    {
    // What is i here
    std::cout << i.first << ' ' << i.second << ',';
    }
    std::cout << std::endl;

    return 0;
    }
    Adrian, Oct 5, 2011
    #1
    1. Advertising

  2. Adrian

    Adrian Guest

    On 10/5/2011 8:37 AM, Adrian wrote:
    > So for a std::map I think the second _RangeT is a class type - is the
    > section that applies and it calls begin() and end() on my may - but the
    > example I tried with an iterator doesnt work.


    Well I can answer that bit for myself - the iterator doesnt work because
    of this
    "for-range-declaration = *__begin;"
    Adrian, Oct 5, 2011
    #2
    1. Advertising

  3. Adrian

    restor Guest

    On Oct 5, 4:37 pm, Adrian <> wrote:
    > Hi all,
    >
    > I am trying out the new range for and I have some questions when it is
    > being used as a map.
    >
    > I see the standard says (6.5.4) that range-based for is equivalent to
    > {
    >     auto && __range = range-init;
    >     for ( auto __begin = begin-expr,
    >        __end = end-expr;
    >        __begin != __end;
    >        ++__begin ) {
    >           for-range-declaration = *__begin;
    >           statement
    >     }
    >
    > }
    >
    > So for a std::map I think the second _RangeT is a class type - is the
    > section that applies and it calls begin() and end() on my may - but the
    > example I tried with an iterator doesnt work.
    >
    > My other general question is - Are the other examples correct/bad
    > style/work by luck etc. I dont understand how range-based for works with
    > a map.
    >
    > Any help/discussion is appreciated.
    >
    > Thanks
    >
    > Adrian Cornish
    >
    > #include <iostream>
    > #include <map>
    >
    > int main(int argc, char *argv[])
    > {
    >     typedef std::map<int, std::string> Map;
    >     Map arr={{9, "nine"}, {8,"eight"}, {7,"seven"}, {6, "six"}, {5,
    > "five"}};
    >
    >     // Test1
    >     for(std::pair<int, std::string> i : arr)
    >     {
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     // same as Test1 I believe
    >     // Test2
    >     for(Map::value_type i : arr)
    >     {
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     // Test3
    > //error: invalid initialization of reference of type
    > // 'std::pair<int, std::basic_string<char> >&' from expression of type
    > // 'std::pair<const int, std::basic_string<char> >'
    > //
    > //   for(std::pair<int, std::string> &i : arr)
    > //   {
    > //      std::cout << i.first << ' ' << i.second << ',';
    > //   }
    > //   std::cout << std::endl;
    >
    >     // Test4
    >     // Maybe this is not the same as Test3 - since the above will not
    > compile
    >     for(Map::value_type &i : arr)
    >     {
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     // Test5
    >     for(const Map::value_type &i : arr)
    >     {
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     // And this works but the not const reference of std::pair does not
    >     // Test6
    >     for(const std::pair<int, std::string> i : arr)
    >     {
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     // Test7
    >     // I really dont get why an iterator does not work? And what doesit
    > mean by
    >     // non-scalar type
    > // error: conversion from 'std::pair<const int, std::basic_string<char> >'
    > // to non-scalar type 'std::map<int, std::basic_string<char>
    >  >::const_iterator
    > // {aka std::_Rb_tree_const_iterator<std::pair<const int,
    > // std::basic_string<char> > >}' requested
    > //   for(Map::const_iterator i : arr)
    > //   {
    > //      std::cout << i->first << ' ' << i->second << ',';
    > //   }
    > //   std::cout << std::endl;
    >
    >     // Test8
    >     for(auto i : arr)
    >     {
    >        // What is i here
    >        std::cout << i.first << ' ' << i.second << ',';
    >     }
    >     std::cout << std::endl;
    >
    >     return 0;
    >
    >
    >
    >
    >
    >
    >
    > }


    Hi,
    I do not have any compiler that supports range-based for at hand but
    from your examples it looks like you are using wrong type for map
    values. Given the map of type std::map<int, std::string>, its
    value_type is std::pair<const int, std::string>. Note the *const*.

    Use the following in place of Test 3:

    for( std::pair<const int, std::string> &i : arr )
    {
    std::cout << i.first << ' ' << i.second << ',';
    }

    Regards,
    &rzej
    restor, Oct 5, 2011
    #3
    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. Replies:
    46
    Views:
    946
    Antoon Pardon
    Jul 25, 2006
  2. Lambda
    Replies:
    2
    Views:
    381
    James Kanze
    Jul 16, 2008
  3. Tomoyuki Kosimizu

    Range does not take an Range object.

    Tomoyuki Kosimizu, Nov 25, 2003, in forum: Ruby
    Replies:
    3
    Views:
    137
    Tomoyuki Kosimizu
    Nov 27, 2003
  4. David Bird
    Replies:
    1
    Views:
    193
    Tiago Macedo
    Jun 23, 2008
  5. Joey Zhou
    Replies:
    5
    Views:
    228
    Joey Zhou
    Apr 15, 2011
Loading...

Share This Page