At times you may need to replace a facet object in a locale by another kind of facet object. In the following example, let us derive from one of the standard facet classes, numpunct, and create a locale object in which the standard std::numpunct facet object is replaced by an instance of our new, derived facet class.
Here is the problem we want to solve. When you print Boolean values, you can choose between the numeric representation of the values "true" and "false", or their alphanumeric representation.
int main(int argc, char** argv)
{
bool any_arguments = (argc > 1); //1
std::cout.setf(ios_base::boolalpha); //2
std::cout << any_arguments << '\n'; //3
// ...
}
Of course, the string representation depends on the language. Hence, the alphanumeric representation of boolean values is provided by a locale. It is the std::numpunct facet of a locale that describes the cultural conventions for numerical formatting. It contains services that return the string representations of the boolean values true and false.
This is the interface of facet numpunct:
namespace std{
template <class charT>
class numpunct : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit numpunct(size_t refs = 0);
char_type decimal_point() const;
char_type thousands_sep() const;
string grouping() const;
string_type truename() const;
string_type falsename() const;
static locale::id id;
// ...
};
}
Now let us replace this facet. To make it more exciting, let's use not only a different language, but also different words for true and false, such as Yes! and No!. For just using another language, we would not need a new facet; we would simply use the right native locale, and it would contain the right facet.
template <class charT> //1
class change_bool_names
: public std::numpunct_byname<charT> //2
{
public:
typedef std::basic_string<charT> string_type;
explicit change_bool_names (const char* name, //3
const charT* t,
const charT* f, size_t refs=0)
: std::numpunct_byname<charT> (name,refs),
true_string(t), false_string(f) { }
protected:
virtual string_type do_truename() const { //4
return true_string;
}
virtual string_type do_falsename() const {
return false_string;
}
private:
string_type true_string, false_string;
};
Now let's create a German locale in which the std::numpunct<char> facet has been replaced by an object of our new derived facet type, as shown in Figure 11:
The code looks like this:
void main(int argc, char** argv)
{
std::locale loc(std::locale("de_DE"), //1
new change_bool_names<char>("de_DE","Ja.","Nein.")); //2
std::cout.imbue(loc); //3
std::cout << "Argumente vorhanden? " //Any arguments?
<< std::boolalpha << (argc > 1) << std::endl; //4
}