Boost logo

Boost :

Subject: Re: [boost] [xint] Third release is ready, requesting preliminary review
From: DE (satan66613_at_[hidden])
Date: 2010-05-04 03:58:01


on 04.05.2010 at 2:20
 Chad Nelson wrote :
> Hm... I *think* I see it now. At least, some of the time I think I do.
> :-) Please check my understanding: you're suggesting that I use
> functions in base_integer to do the allocation, and have them call other
> functions in base_integer to do the things that are different between
> fixed_integer and the variable-length integers. But then override those
> functions in the fixed_integer classes, not as virtual functions, but
> using CRTP to call the overridden functions. Am I right?

let me try to explain

suppose the interface of all your concrete classes (i.e. 'integer',
'nothrow_integer' and 'fixed_integer') is homogeneous
that is all classes have identical names for respective members with
consistent semantics

then each of the classes inherits the base class

  template<typename type>
  class base_integer {};

in the following way

  class integer : public base_integer<integer>
  {/*...*/};

then you can write template functions for all types in the following
manner:

  template<typename int_type>
  void foo(const base_integer<int_type>&);
  template<typename type1, typename type2>
  void bar(const base_integer<type1>&, const base_integer<type2>&);

such functions will handle all types derived from base_integer
providing their type as template argument

an implementation of such a function can be like this:

  template<typename type>
  type negate(const base_integer<type> &a)
  {
    const type &instance = *static_cast<type*>(&a);
    return instance.negated();
  }

notice that this function returns a concrete type deduced
automatically
also this function implies that all concrete types have 'negated()'
member function (as an example)

also the ugly static_cast may be wrapped in a functions:

  template<typename type>
  type &get_instance(base_integer<type> &a) { return *static_cast<type*>(&a); }
  template<typename type>
  const type &get_instance(const base_integer<type> &a) { return *static_cast<const type*>(&a); }

designing a lib this way you have a header with those (CRTP'ed)
template stuff while concrete types reside in header and/or cpp file
as is convenient for you
as well this approach is type safe as long as 'base_integer'
parameterized according to the contract

please think about it, it is a very powerful design technique, also it
may solve a whole lot of troubles now and later

i like this theme very much and will happily write more words on this
on your demand
  

-- 
Pavel
P.S.
if you notice a grammar mistake or weird phrasing in my message
please point it out

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk