jeudi 20 janvier 2022

C++11 Template Method to Stream std::map to std::cout

Objective: Implement a template method that generically allows streaming std::map instances to std::cout

Problem: I'm getting undefined behavior, where my code executes without errors and other times a segfault. Either way the std::map content do print to the command window in entirety.

What I've tried:

    /* Import dependencies */
    #include <iostream>
    #include <string>
    #include <vector>
    #include <map>

    /* Declare a recursive template overload of the ostream << operator for printing std::vector types */
    template<typename T>
    std::ostream& operator<<(std::ostream& stream, std::vector<T> vec)
    {
        //Save repetitive calls to check .size()
            int container_size = vec.size();
            
        //Pre-allocate loop iterator
            int indx = 0;
            
        //Check if the input vector is empty
            if( container_size > 0 )
            {
                //Stream character for the start of a container
                    stream << "\n\t{ ";               
                    
                //For each element of the input container, could be a value or nested container
                    for(indx; indx < container_size; indx++)
                    {
                        //Execute based on iterator position within container
                            if( indx < ( container_size - 1 ) )
                            {
                                //Print value, or recurse nested container to << template
                                    stream << vec[ indx ] << ", ";
                            }
                            else
                            {
                                //Stream last value and terminate with character
                                    stream << vec[ indx ] << " }";
                            }
                    }
            }
            
        //Default & final execution
            return stream;
            
    };

    /* Template method to stream std::map instances to std::cout */
    template<typename KeyT, typename ValueT>
    std::ostream& operator<<(std::ostream& os, std::map<KeyT,ValueT> mapInst)
    {
        for(auto& item : mapInst)
        {
            std::cout << item.first << ":" << item.second << "\n";    
        }
    }

    /* Main routine */
    int main()
    {
        //Declare a map
            std::map< std::string, std::vector< std::vector<double> > > tmp;
            
        //Make some stuff to insert into the map
            std::vector< std::vector<double> > v1 = { { 3000.28, 3000.11, 1e+006, 3000.02, 1e+006, 3000.28, 3016.76, 3014.47, 3014.39, 1e+006, 1e+006, 1e+006 },
                                                      { 3000.28, 3000.11, 3000.02, 3000.02, 1e+006, 3000.28, 3016.76, 1e+006, 3014.39, 3012.26, 3012.35, 3010.39 },
                                                      { 3000.28, 1e+006, 3000.02, 3000.02, 3000.11, 3000.28, 1e+006, 3014.47, 3014.39, 3012.26, 3012.35, 1e+006 },
                                                      { 3000.28, 1e+006, 3000.02, 3000.02, 3000.11, 3000.28, 3016.76, 3014.47, 3014.39, 1e+006, 3012.35, 3010.39 },
                                                      { 3000.28, 1e+006, 1e+006, 1e+006, 1e+006, 1e+006, 3016.76, 3014.47, 3014.39, 3012.26, 1e+006, 3010.39 },
                                                      { 3000.28, 3000.11, 1e+006, 3000.02, 3000.11, 1e+006, 3016.76, 1e+006, 3014.39, 3012.26, 3012.35, 3010.39 },
                                                      { 3000.28, 3000.11, 3000.02, 3000.02, 3000.11, 1e+006, 1e+006, 3014.47, 3014.39, 3012.26, 3012.35, 3010.39 } };
            
            std::vector< std::vector<double> > v2 = { {10.0,11.0,12.0}, {-100.0,-200.0,-300.0}, {0.123,0.456,0.789} };
                                         
        //Put the data into the map
            tmp.insert( std::make_pair( "SomeKey", v1 ) );
            tmp.insert( std::make_pair( "SomeOtherKey", v2 ) );
        
        //Stream the map to cout
            std::cout<<"My MAP = \n"<<tmp<<"\n\n";
        
        //Exit the main program
            return 0;
            
    }

Aucun commentaire:

Enregistrer un commentaire