Boost logo

Boost :

Subject: Re: [boost] Design conventions; passing functors
From: Joachim Faulhaber (afojgo_at_[hidden])
Date: 2008-12-01 12:30:19


2008/11/29 Neal Becker <ndbecker2_at_[hidden]>:
> I used to like template template, but I've decided it's fairly useless. The problem is:
>
> template<template<class A>a>
> does not match a class with a default parameter. So, for example, suppose you have a class where you specify a container class as a parameter. For example:
>
> template<typename T, template<class Vec> vec >
> class my_class ...
>
> This won't match
> my_class<int, std::vector>
>
> Because std::vector has a defaulted alloc parameter. This ruins the design (my_class shouldn't need to know anything about default parameters of the container. How could it know what other vector-like classes there could be and what default parameters they might have?)
>

That's an interesting point, you are making, which I had not realized
clearly before.

Using template type parameters, there is a much bigger set
of possible instance types, vector implementations in your example.

With template template parameters the match must be exact:

template<class T,
         // matches only binary vector templates
         template<class,class>class Vec,
         class A = std::allocator<T> >
class my_class
{
public:
  typedef Vec<T,A> vec_type;
  my_class():_vec(1,static_cast<T>(42))
  { std::cout<<"Aswer: "<<_vec[0]<<endl; }
private:
  vec_type _vec;
};

void template_default_problem()
{ my_class<double, std::vector> myInst; }

Yet, I did not deliberately become a template template
afficionado. They helped me to solve a problem in
my library design. I intended to design interval container
template parameters as closely as possible to their
std::container cousins.

Here is a simplified version of interval_set:

template<class T,
         class C = std::less<T>,
         class A = std::allocator<T> >
class interval_set
{
public:
  typedef
    std::set<interval<T>,
      exclusive_less<interval<T> >
      A::allocator_template<interval<T> >//error
> impl_type; // ^^^^ No language support

  typedef std::set<T,C,A> atomized_type;

  // Return the interval set as a set of elements
  void atomize(atomized_type& atomized);
  ...
private:
  impl_type impl_set;
};

In order to implement things like the atomize function
that returns the interval set as a set of elements I
needed to instantiate the allocator template for different
instance types: interval- and element-types.

This is made possible by using template template:

template<
  class T,
  class C = std::less<T>,
  template<class>class A = std::allocator
>
class my_interval_set
{
public:
  typedef
    std::set<interval<T>,
      exclusive_less<interval<T> >
      A<interval<T> > //ok now
> impl_type;

  typedef
    std::set<T,C,
      A<T> //Same allocator,
             //different instances
> atomized_type;

  // Return the interval set as a set of elements
  void atomize(atomized_type& atomized);
  ...
private:
  impl_type impl_set;
};

So far template template params has helped me a lot and,
yes, I still like them ;-) But I also realize a growing
list of downsides, to which you have added one more
item.

Cheers Joachim


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