Boost logo

Boost Users :

From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2005-08-23 17:33:35


----- Mensaje original -----
De: "Alan M. Carroll" <amc_at_[hidden]>
Fecha: Martes, Agosto 23, 2005 8:52 pm
Asunto: [Boost-users] Using MPL for conditional compilation

> I am building a templated container class C. Normally it acts just
> like an stl::map. However, if the mapped_type of a container
> C<key1, value1> is also a specialization of C (value1 = C<key2,
> value2>) then the key types of the containers are merged in to a
> tuple yielding a container that acts like C< <key1, key2>, value2 >.
>
> Obviously the MPL has been quite useful for this but I'm not clear
> on the best style / usage for a particular effect.
>
> Inside C, the insert method has two parts, the part that's the
> same regardless of whether C is merged container and the part that
> isn't. How should I arrange to have different code executed
> depending on whether C is a merged container or not? I have a
> class static const bool IS_OUTER that is set to true for merged
> containers and false otherwise.
>
[...]
>
> 5) Use traits classes keyed by IS_OUTER to provide the differing
> implementations.

If the *syntactic* differences between both flavors can
be reduced to only different definitions for key_type and
mapped_type, I'd use something like your option 5) :

template<typename Key, typename Value>
class your_container
{
  static bool const IS_OUTER=...;

  typedef typename boost::mpl::if_c<
    IS_OUTER,
    struct outer_tag,
    struct inner_tag
>::type flavor;

public:
  typedef typename boost::mpl::if_c<
    IS_OUTER,
    boost::tuple<Key,typename Value::key_type>,
    Key
>::type key_type;

  typedef typename boost::mpl::if_c<
    IS_OUTER,
    typename Value::mapped_type,
    Value
>::type mapped_type;

  // example of memfun with alternate implementations

  const_iterator find(const key_type& k)const
  {
    return find_impl(k,flavor());
  }

  // shared menfuns do not need any special machinery

private:
  
  // alternate implementations of find

  const_iterator find_impl(const key_type& k,outer_tag)const
  {
    ...
  }

  const_iterator find_impl(const key_type& k,inner_tag)const
  {
    ...
  }
};

With this scaffolding set up, it is guaranteed that only the
appropriate *_impl memfuns are compiled in each case, and
the runtime penalty should be optimized away to zero.
OTOH, if the number of memfuns with alternate implementations
is very large with respect to shared memfuns, you might want
to go for fully separated classes.

HTH,

Joaquín M López Muñoz
Telefónica, Investigaión y Desarrollo


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net