Questions about new range for

A

Adrian

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 said:
::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;
}
 
A

Adrian

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;"
 
R

restor

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top