FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
C++
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
TABLE OF CONTENTS
September 25, 2007

Straightforward Settings

(Page 2 of 4)

Runtime Constants

When settings are this easy, you can get carried away. In fact, a lot of the application constants can become runtime constants (that is, be read as settings). This brings flexibility up a gear—which is great! Imagine doing profiling—you go through the .ini file, change a few values, see how the application behaves. Tuning your app will become a lot less painful.

One thing to remember is that when using a runtime constant, use the const_ function, instead of setting. You'll have a few advantages:

  • Readability: the one reading the code will understand it's a read-only setting (more important: a constant)
  • when using const_, the library will enforce that you can't use it as a setting at all. In debug, you'll get a failed assertion. In release, you can choose to throw an exception (see "Error Handling" below)

Note that you can use forced get when using const_. Listing Four shows you how to use the constants.

int r = const_("user.retries");
std::string welcome = const_("app.welcome_msg");
int max_users = const_("app.max_users");
int def_size = 
  const_<int>("w.def_width") * const_<int>("w.def_height");
Listing Four

The Dot Makes a Point

The setting names contain dots in them. This is intentional. First of all, it delimits scope of the setting: "chart.window.width" tells you that it's a setting related to the "chart" module, it's about its window, and it's about the window's width.

More than that, the dots can specify the actual storage destination: be it a file, a read-only file, the registry, some web site, etc. Based on the name of the setting (as you'll see below), the library will select where it reads or writes the setting.

The predefined storage classes are file_storage and registry_storage, but you can extend the library, by adding your own storage classes.

Note that for a setting, its type must be IOstream friendly (have operator<< defined, in order to be read, and operator>> defined, in order to be written). As a bonus, I allow for automatic conversions between strings of different types (from std::string to std::wstring, and vice versa).

The storage class will always deal with the setting values as strings. However, for each setting it deals with, it will also know its original type, thus, it can optimize the storage. For instance, the registry storage class will keep integers as DWORDs in the registry. See Listing 5.

struct setting_storage  
{
  ...
  virtual void get_setting( 
    const std::string &name, std::string &val,
    const std::type_info&) const = 0;
  virtual void set_setting( 
    const std::string &name, const std::string &val,
    const std::type_info& ) = 0;
  ...
};

struct registry_setting_storage : setting_storage {
  ...
  virtual void set_setting( 
    const std::string &name, const std::string &val,
    const std::type_info& t) {
      if ( t == typeid(int) || t == typeid(long) ||
           t == typeid(short) || ...)
             write_to_registry_as_DWORD(name, val);
      else
             write_to_registry_as_SZ_string(name,val);
  }
};
Listing Five

As a side note, the file_storage class has an option to save the settings at a certain interval (on a dedicated thread). file_storage also allows you to have comments, as shown in Listing 6.

# when connecting to server,
# and it fails, how many times should we try again?
app.retry_count=10

# when delete dummy temporary files, at what period should we do it?
app.del_temp_files_ms=5000
Listing Six

Previous Page | 1 Usability: More than Meets the Eye | 2 Runtime Constants | 3 Initialization | 4 Defaults Next Page
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK