Jez Higgins

Freelance software generalist
software created
extended or repaired


Older posts are available in the archive or through tags.

Feed

Follow me on Twitter
My code on GitHub

Contact
About

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 generalist
software created
extended or repaired

Older posts are available in the archive or through tags.

Feed

Follow me on Twitter
My code on GitHub

Contact
About