[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