[GiNaC-devel] Class container vs. the holy standard?

David Fang fang at csl.cornell.edu
Mon Apr 17 01:50:47 CEST 2006


> Triggered by Debian bug #362220 [0] I submitted GCC bug report #27178
> [1] only to be told that container.h made use of a GCC extension that
> will have been removed from GCC in the upcoming 4.2.0 release [2].
> Basically, where we were simply writing this:
>
>   template <template <class> class> class container;
>   typedef container<std::list> lst;
>
> we now have to write the more cumbersome:
>
>   template <template <class, class> class> class container;
>   typedef container<std::list> lst;
>
> This is because std::list has two template parameters, the element type
> and the allocator type.  Ugh.

Hi,
	I saw the same problem coming in my own project, so I made some
provisional changes in my own source to help.  I don't know if my
technique is directly applicable to your particular situation, but it
might provide some ideas for a workaround.

	I wrote a forward declaration header for each class template
definition in STL.  Example:

// \file "util/STL/allocator_fwd.h" ------------------------------------
namespace std {
template <typename> class allocator;
}

// \file "util/STL/list_fwd.h" -----------------------------------------
#include "util/STL/allocator_fwd.h"

namespace std {
template <class T, class Alloc>
class list;
}

namespace not_std {
template <class T>
struct default_list {
        typedef std::list<T, std::allocator<T> >     type;
};
}

//----------------------------------------------------------------------

When I want to name the default std::list<T> type without without
requiring its complete type, I can refer to default_list<T>::type, which
has explicitly bound the trailing template arguments to their STL
defaults.  Advantage: avoids including <list> in certain headers where the
complete type is not needed (e.g. return types, pointer/reference to...
uses).

And how does this relate to your container<T> ...

> It's ugly, because the intent was clearly to not bother the user with
> implementation details like the allocator. From the user's perspective,
> the intent is to express "container of T", never mind what type of
> container.  I've attached a patch against CVS GiNaC-1.3 that converts
> all places flaged as errors in GCC 4.2 20060415 (experimental) to:
>
>   template <template <class T, class = std::allocator<T> > class> class X;
>   typedef X<std::list> lst;

The situation described above is a workaround to the lack of "template
typedefs" in (present) std C++, which is our common underlying problem.
A kludgy variation might use inheritance, but this doesn't result in
equivalent types:

namespace not_std {
template <class T>
class default_list : public std::list<T, std::allocator<T> > {
        typedef std::list<T, std::allocator<T> >     type;
};
}

(This, however, does require std::list's complete definition.)
You could then write something like this (using your example):

	template <template <class> class> class X;
	typedef X<not_std::default_list> lst;

Again, not the greatest solution because of the inheritance relationship
separating you from the actualy type you want.

Rewriting your definitions to use a nested ::type member might only work
for these non_std wrappers because the STL containers don't have
self-referential 'type' member typedefs.

> This is ugly as sin, because I don't think that we really wanted to
> express "STL-container of T", as the changed code now appears to imply.
>
> Any suggestions?

I might see what other template metaprogramming techniques have to offer.
I'm only a newbie in this subject, still learning on the fly.  I would be
very interested to hear what solution you end up using.



David Fang






More information about the GiNaC-devel mailing list