lilzz
Posts: 411
Joined: Sat Nov 30, 2013 5:27 pm

How to output values of std::map

Mon Dec 14, 2015 9:10 pm

Code: Select all

std::map<uint8_t, int> inst_used;

  for (uint8_t gc : main_classes)
    {
      extend( inst_used, 0);
     std::cout << inst_used;
    }
The code crashed when I did std:cout to show the values of inst_used. std::map

what's the best way to display the entire values of inst_used.
I try to debug and single-step it but the variable inst_used doesn't show the values inside.

User avatar
AndyD
Posts: 2334
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: How to output values of std::map

Mon Dec 14, 2015 11:39 pm

@lilzz you really need to put more context into your posts. What is main_classes (other than something that provides begin() and end())? Why are you iterating over main_classes and then not using gc? What does extend do?

Anyway, here is some code to print a std::map<uint8_t, int>:

Code: Select all

#include <cstdint>
#include <iostream>
#include <map>

int main()
{
    std::map<uint8_t, int> used = {{1,4}, {2,5}, {3,6}};

    for (const auto& iter : used)
    {
        std::cout
            << "key: "
            << static_cast<int>(iter.first)
            << " value: "
            << iter.second
            << "\n";
    }

    return 0;
}
Prints:

Code: Select all

key: 1 value: 4
key: 2 value: 5
key: 3 value: 6

lilzz
Posts: 411
Joined: Sat Nov 30, 2013 5:27 pm

Re: How to output values of std::map

Tue Dec 15, 2015 5:31 am

what if the
std::map<object1, object2> used = {{obj1, obj2} {obj3, obj4}};

for (const auto& iter : used)
{
std::cout
<< "object1 name: "
<<(iter.first.m_name)
<< "object2 name: "
<< iter.second.m_name
<< "\n";
}

That doesn't seem to work. iter.first. there is auto fill in element in my ide.

User avatar
AndyD
Posts: 2334
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: How to output values of std::map

Tue Dec 15, 2015 6:52 am

lilzz wrote:what if the

Code: Select all

std::map<object1, object2> used = {{obj1, obj2} {obj3, obj4}};

for (const auto& iter : used)
{
    std::cout
        << "object1 name: "
        <<(iter.first.m_name)
        << "object2 name: "
        << iter.second.m_name
        << "\n";
}
That doesn't seem to work. iter.first.
Lilzz, a class is a type, an object in an instance of a class. So to change your example slightly:

Code: Select all

std::map<class1, class2> used = {{obj1, obj2} {obj3, obj4}};

for (const auto& iter : used)
{
    std::cout
        << "object1 name: "
        <<(iter.first.m_name)
        << "object2 name: "
        << iter.second.m_name
        << "\n";
}
So, your code will only work if class1 and class2 have a public member variable called m_name, and that what ever type m_name is, it can be streamed.
lilzz wrote:there is auto fill in element in my ide.
So what does the auto fill want to put there?
Last edited by AndyD on Tue Dec 15, 2015 10:27 am, edited 1 time in total.

lilzz
Posts: 411
Joined: Sat Nov 30, 2013 5:27 pm

Re: How to output values of std::map

Tue Dec 15, 2015 7:34 am

It doesn't present class functions or class variable when I do iter.first.
iter.first error :request for member first in iter, which is of pointer type class1 * const (maybe you meant to use -> ?


Iter->first error: class class1 has no member named first


So it doesn't work.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 26660
Joined: Sat Jul 30, 2011 7:41 pm

Re: How to output values of std::map

Tue Dec 15, 2015 9:59 am

The output from iterating through a map is a std::pair<> containing the two items per map entry.

That's where the .first and .second come from. Here some code from something I am working on now...The second part of the pair is a class pointer that has a print function (you could probably use << if you class has an ostream << override.

Code: Select all

    // For all the entries in the map...
    for(auto const &ent1 : obj.metadataMap)
    {
        ent1.second->print(os);
    }
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed.
I've been saying "Mucho" to my Spanish friend a lot more lately. It means a lot to him.

User avatar
AndyD
Posts: 2334
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: How to output values of std::map

Tue Dec 15, 2015 10:12 am

lilzz wrote:It doesn't present class functions or class variable when I do iter.first.
iter.first error :request for member first in iter, which is of pointer type class1 * const (maybe you meant to use -> ?

Iter->first error: class class1 has no member named first

So it doesn't work.
If it doesn't work, then your code example doesn't match the code you are working on. This works:-

Code: Select all

#include <iostream>
#include <map>
#include <string>

//---------------------------------------------------------------------

struct Class1
{
    Class1()
    :
        m_number{++s_count},
        m_name{"Class1 - instance " + std::to_string(m_number)}
    { }

    int m_number;
    std::string m_name;

    static int s_count;
};

int Class1::s_count{0};

bool operator <(const Class1& lhs, const Class1& rhs)
{
    return lhs.m_number < rhs.m_number;
}

//---------------------------------------------------------------------

struct Class2
{
    Class2()
    :
        m_number{++s_count},
        m_name{"Class2 - instance " + std::to_string(m_number)}
    { }

    int m_number;
    std::string m_name;

    static int s_count;
};

int Class2::s_count{0};

//---------------------------------------------------------------------

int main()
{
    Class1 obj1;
    Class2 obj2;
    Class1 obj3;
    Class2 obj4;

    std::map<Class1, Class2> used = {{obj1, obj2}, {obj3, obj4}};

    for (const auto& pair : used)
    {
        std::cout
            << "object1 name: "
            << pair.first.m_name
            << ", object2 name: "
            << pair.second.m_name
            << "\n";
    }

    return 0;
}
prints:

Code: Select all

object1 name: Class1 - instance 1, object2 name: Class2 - instance 1
object1 name: Class1 - instance 2, object2 name: Class2 - instance 2
Are you sure you are using a std::map?

lilzz
Posts: 411
Joined: Sat Nov 30, 2013 5:27 pm

Re: How to output values of std::map

Tue Dec 15, 2015 9:49 pm

ok, my mistake.
the above is for std::set instead of std::map

I need a way to output for std::set.

User avatar
Paeryn
Posts: 2966
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: How to output values of std::map

Tue Dec 15, 2015 11:06 pm

If it's a set, and the type of the elements has an appropriate output operator<< then you can just iterate through and print.

Code: Select all

#include <iostream>
#include <set>

int main()
{
  std::set<int> used = {5, 3, 8};

  for (const auto& iter : used) {
    std::cout << iter << std::endl;
  }
  return 0;
}
If the set's element type doesn't have an appropriate output operator you'll need to call something to generate an output-able version of the iter variable with something like (assuming the type has a function to_string() which returns a printable string representation)

Code: Select all

#include <iostream>
#include <set>
#include <string>

// MyClass orders the set based on value.
class MyClass {
  int value;
  std::string name;
public:
  MyClass(int v, std::string n) : value(v), name(n) {};
  std::string to_string() const
  {
    return "Value:" + std::to_string(value) + "Name:" + name;
  }
  struct comp {
    bool operator() (const MyClass &lhs, const MyClass &rhs) const
    { return lhs.value < rhs.value;}
  };
};

int main()
{
  std::set<MyClass,MyClass::comp> used = {{3,"Three"}, {1,"One"}, {5,"Five"}};

  for (const auto& iter : used) {
    std::cout << iter.to_string() << std::endl;
  }
  return 0;
}
Or just output the parts of the element if you can access them :-

Code: Select all

#include <iostream>
#include <set>
#include <string>

struct MyClass {
  int value;
  std::string name;
  MyClass(int v, std::string n) : value(v), name(n) {};
  struct comp {
    bool operator() (const MyClass &lhs, const MyClass &rhs) const
    { return lhs.value < rhs.value;}
  };
};

int main()
{
  std::set<MyClass,MyClass::comp> used = {{3,"Three"}, {1,"One"}, {5,"Five"}};

  for (const auto& iter : used) {
    std::cout << iter.name << " (" << iter.value << ")" << std::endl;
  }
  return 0;
}
She who travels light — forgot something.

lilzz
Posts: 411
Joined: Sat Nov 30, 2013 5:27 pm

Re: How to output values of std::map

Wed Dec 16, 2015 4:43 pm

@paeryn

if std::set < class1, class 2>

both class 1, class 2 has m_name, m_value

for (const auto& iter : used) {
iter.m_name //class2 or class2 m_name?
iter.m_value //class1 or class 2 m_value?
}

your example is not clear

User avatar
Paeryn
Posts: 2966
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: How to output values of std::map

Wed Dec 16, 2015 5:24 pm

Ermm... A set only has one element type. The second class parameter provides the compare function.
By using std::set<class1, class2> you are declaring a set of class1 objects and using class2 to do the comparing, e.g. if using int as the class then

Code: Select all

std::set<int>
is the same as

Code: Select all

std::set<int, std::less<int>>
So to use std::set<class1, class2> you would need something like (using int as class1 and compare as class2)

Code: Select all

#include <iostream>
#include <set>
#include <string>

// compare is the class/struct that compares values for the set
struct compare {
  bool operator() (const int &lhs, const int &rhs) const
  {
    return lhs < rhs;
  }
};

int main()
{
  std::set<int,compare> used = {1, 2, 3};

  for (const auto& iter : used) {
    std::cout << iter << std::endl;
  }
  return 0;
}
This lets you tell the compiler how to compare two elements (in the case of something more complex than an int).
She who travels light — forgot something.

Return to “C/C++”