Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Printing an object in multiple ways

Tags:

c++

iostream

If I take a simple date object:

#include <iostream>
using namespace std;

class Date
{
    int mo, da, yr;
public:
    Date(int m, int d, int y)
    {
        mo = m; da = d; yr = y;
    }
    friend ostream& operator<<(ostream& os, const Date& dt);
};

ostream& operator<<(ostream& os, const Date& dt)
{
    os << dt.mo << '/' << dt.da << '/' << dt.yr;
    return os;
}

int main()
{
    Date dt(5, 6, 92);
    cout << dt;
}

and I wish to have the option to print it in a way people from the UK will understand i.e.

ostream& operator<<(ostream& os, const Date& dt)
{
    os << dt.da << '/' << dt.mo << '/' << dt.yr;
    return os;
}

How is the best way to allow users of the class to choose between 2 (or more) print options?

I was thinking of something similar to returning two separate classes from two methods of the date class that each have their operator<< overloaded in the 2 different ways. But Is there a better way?

code from: http://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx

like image 895
jayjay Avatar asked Dec 11 '22 03:12

jayjay


1 Answers

A culture-dependent stream formatting (such as for dates, monetary) should base on std::locale settings of a given stream:

#include <locale>
#include <ostream>

std::ostream& operator<<(std::ostream& os, const Date& dt)
{
    std::time_base::dateorder d = std::use_facet<std::time_get<char>>(os.getloc())
                                      .date_order();

    if (d == std::time_base::dmy)
    {
        // Selected format is day / month / year
        os << dt.da << '/' << dt.mo << '/' << dt.yr;
    }
    else if (d == std::time_base::mdy)
    {
        // Selected format is month / day / year
        os << dt.mo << '/' << dt.da << '/' << dt.yr;
    }
    else
    {
        // Default format is year . month . day
        os << dt.yr << '.' << dt.mo << '.' << dt.da;
    }

    return os;
}

This allows users of your class to select between different formats (assuming the locale are supported), so that the output is adjusted for a given culture:

Date d{ 9, 8, 2014 };

std::cout.imbue(std::locale("en_US.utf8"));
std::cout << d << std::endl;

std::cout.imbue(std::locale("de_DE.utf8"));
std::cout << d << std::endl;

DEMO

like image 159
Piotr Skotnicki Avatar answered Dec 27 '22 05:12

Piotr Skotnicki