Extending messages by derivation

If you are on a platform without file support, or you do not want to use files for messages for other reasons, you may derive from messages and override the virtual methods as described by the standard. Additionally you can take advantage of the EWL C++ specific protected interface of messages if you wish (to make your job easier if portability is not a concern).

The messages facet has the non-virtual protected member:

  string_type& __set(catalog c, int set, int msgid);
  

You can use this to place the quadruple ( c, set, msgid, string) into messages' database. The constructor of the derived facet can fill the database using multiple calls to __set. Below is an example of such a class. This example also overrides do_open to double check that the catalog name is a valid name, and then return the proper catalog number. And do_close is also overridden to do nothing. The messages destructor will reclaim all of the memory used by its database:

The main program (client code) in the Example of extending message by derivation is nearly identical to the previous example. Here we simply create and use the customized messages facet. Alternatively we could have created a locale and installed this facet into it. And then extracted the facet back out of the locale using use_facet as in the first example.

Listing: Example of extending message by derivation
#include <locale>
#include <iostream>

#include <string>

#include <map>

class MyMessages

   : public std::messages<char>

{

public:

   MyMessages();

protected:

   virtual catalog do_open(const std::string& fn, 

         const std::locale&) const;

   virtual void    do_close(catalog) const {}

private:

   std::map<std::string, catalog> catalogs_;

};

MyMessages::MyMessages()

{

   catalogs_["my_messages"] = 1;

   __set(1, 1, 1) = "set 1: first message";

   __set(1, 1, 2) = "set 1: second message";

   __set(1, 1, 3) = "set 1: third message";

   __set(1, 2, 1) = "set 2: first message";

   __set(1, 2, 2) = "set 2: second message";

   __set(1, 2, 3) = "set 2: third message";

}

MyMessages::catalog

MyMessages::do_open(const std::string& fn, const std::locale&) const

{

   std::map<std::string, catalog>::const_iterator i =

          catalogs_.find(fn);

   if (i == catalogs_.end())

      return -1;

   return i->second;

}

int main()

{

   typedef MyMessages Msg;

   Msg ct;

   Msg::catalog cat = ct.open("my_messages",

         std::locale::classic());

   if (cat < 0)

   {

      std::cout << "Can't open message file\n";

      return 1;

   }

   std::string eof("no more messages");

   for (int set = 1; set <= 2; ++set)

   {

      std::cout << "set " << set << "\n\n";

      for (int msgid = 1; msgid < 10; ++msgid)

      {

         std::string msg = ct.get(cat, set, msgid, eof);

         if (msg == eof)

            break;

         std::cout << msgid << "\t" << msg << '\n';

      }

      std::cout << '\n';

   }

   ct.close(cat);

}

The output of this program is:

set 1

  1   set 1: first message
  2   set 1: second message
  3   set 1: third message
  

set 2

  1   set 2: first message
  2   set 2: second message
  3   set 2: third message