By string_abstraction we mostly refer to use of ext::string_abstraction_interface from which the ext::string_abstraction template (and all its specializations) is derived. This simple facility allows their users to postpone a resolution whether the string is of wide-characters or not from initialization to its actual use.
struct ext::string_abstraction_interface {
public:
virtual bool
is_wide () const = 0;
virtual std::string to_string () const = 0;
virtual std::wstring to_wstring () const = 0;
public:
virtual ~string_abstraction_interface () throw ();
};
template <typename T>
struct ext::string_abstraction : public ext::string_abstraction_interface {
public:
typedef T underlying_type;
public:
string_abstraction (const std::basic_string <T> &);
virtual ~string_abstraction () throw ();
virtual bool
is_wide () const;
virtual std::string to_string () const;
virtual std::wstring to_wstring () const;
};
namespace ext {
template <typename T>
string_abstraction_interface * abstract_string (const std::basic_string <T> &)
string_abstraction_interface * abstract_string (const char *);
string_abstraction_interface * abstract_string (const wchar_t *);
};
A pointer to ext::string_abstraction_interface is used wherever the string abstraction is needed. Then, when the string is finally available (mostly passed by a function template), an actual ext::string_abstraction is new-allocated and assigned to the appropriate ext::string_abstraction_interface pointer.
The ext::abstract_string function (a set of overloaded functions) is available to simplify the actual initialization of the ext::string_abstraction_interface pointer.
#include <ext/c++>
class C {
private:
ext::string_abstraction_interface * name;
ext::string_abstraction_interface * param;
public:
template <typename T, typename U>
C (const std::basic_string <T> & _name,
const std::basic_string <U> & _param)
: name (ext::abstract_string (_name)),
param (ext::abstract_string (_param)) {};
C (const char * _name, const char * _param)
: name (ext::abstract_string (_name)),
param (ext::abstract_string (_param)) {};
C (const wchar_t * _name, const wchar_t * _param)
: name (ext::abstract_string (_name)),
param (ext::abstract_string (_param)) {};
C (const wchar_t * _name, const char * _param)
: name (ext::abstract_string (_name)),
param (ext::abstract_string (_param)) {};
C (const char * _name, const wchar_t * _param)
: name (ext::abstract_string (_name)),
param (ext::abstract_string (_param)) {};
~C () {
delete this->name;
delete this->param;
};
void operator () () {
// postponed resolution
if (this->name->is_wide () || this->param->is_wide ())
SomeApiFunctionW (this->name->to_wstring ().c_str (),
this->param->to_wstring ().c_str ());
else
SomeApiFunctionA (this->name->to_string ().c_str (),
this->param->to_string ().c_str ());
};
};
See first remark for details to this example.
The ext::string_abstraction_interface is successfully used when abstracting away the duality of Windows API functions (A/W variants) where the A-variant is called when neither argument is a wide-character string and W-variant otherwise. This allows a single middle-ware class to be used on Windows 9x/Me (these does not support those W-variants) and still support Unicode (wide-characters) in projects where neccessary at the same time.
[index]