Jez Higgins

Freelance software grandad
software created
extended or repaired


Follow me on Twitter
Applications, Libraries, Code
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed

Tuesday 06 December 2005 Arabica: See the problem?

Here's a bit of Arabica code -
  template<class string_type,
           class string_adaptor =
               Arabica::default_string_adaptor<string_type> >
  class XMLReader : public DEF_SAX_P<string_type, string_adaptor>
  {
    ...
  };
and here's another bit
  template<class string_type,
           class COMInitializer_type = COMSingleThreadInitializer,
           class string_adaptor_type =
               Arabica::default_string_adaptor<string_type> >
  class msxml2_wrapper : public SAX::basic_XMLReader<string_type>
  {
    ...
  };

DEF_SAX_P is a macro which expands to the default SAX class name, quite possibly msxml2_wrapper. See the problem? I've built myself a situation where not only does msxml2_wrapper have a different number of parameters than the my other wrappers, the order of the parameters is different too. What a twit. I can't recall the full history (or I'd probably have avoided it) but there's a good reason for msxml2_wrapper's extra parameter, the extra parameter being in an odd place, and for the DEF_SAX_P macro.

So there's the problem. A few years ago, I'd have considered this largely intractable without breaking existing code. Now though, this is a simple meta-programming issue -

struct nil_t { };

template <typename BaseT,
             typename DefaultT,
             typename T0,
             typename T1>
struct get_param
{
  typedef typename boost::mpl::if_<
      boost::is_base_and_derived<BaseT, T0>
      , T0
      , typename boost::mpl::if_<
            boost::is_base_and_derived<BaseT, T1>
          , T1
          , DefaultT
        >::type
    >::type type;
};

template<class string_type,
         class T0 = nil_t,
         class T1 = nil_t>
class msxml2_wrapper : public SAX::basic_XMLReader<string_type>
{
  typedef typename get_param<COMInitializer_tag,
                             COMSingleThreadInitializer,
                             T0,
                             T1>::type COMInitializer_type;
  typedef typename get_param<Arabica::string_adaptor_tag,
                             Arabica::default_string_adaptor<string_type>,
                             T0,
                             T1>::type string_adaptor_type;
  ...
};
This lets us specify the initialiser and string_adaptor parameters in either order. Consequently, the XMLReader definition can be extended to take a third parameter. For people who need pass extra parameters to MSXML, they can. Everyone else can ignore it. Nice.


Tagged code, arabica, xml, and c++


Jez Higgins

Freelance software grandad
software created
extended or repaired

Follow me on Twitter
Applications, Libraries, Code
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed