|
Boost : |
From: Jonathan Turkanis (technews_at_[hidden])
Date: 2004-11-04 13:59:45
"James Harris" <james.harris_at_[hidden]> wrote in message
news:clvhdd$3rp$1_at_sea.gmane.org...
> Hello Boost Members,
>
> I have written a small library of meta-functions that allow rebinding of
> template arguments <snip> I am posting in an attempt to guage interest and
> hopefully receive pointers on the library proposal process.
>
>
> The library provides the following meta-functions:
>
> rebind<int index, class rebind_type, class source_type> -- rebind
> template arguments
To be MPL-friendly, it should be
template<typename N, typename rebind_type, typename source_type>
struct rebind;
<snip>
> template <class A, class B, class C>
> class foo { };
>
> typedef foo<int, int, int> source_type;
> typedef rebind<1, char, source_type>::type rebound_type; // rebound_type
> equates to foo<int, char, int>
On two occassions recently I found myself implementing a
template-argument-rebinding facility and wished for a generic solution.
Unfortunately, I just looked at my two use cases and found that the metafunction
you describe would not be much help. Let me describe these cases, to give you an
idea of the problems which a generic rebind facility should IMO be able to
solve.
--- 1) In my yet-to-be documented or posted "Format Lite" library -- a lightweight alternative to Reece Dunne's recently reviewed Output Formatting library -- I use class template specializations as CSS-type selectors to indicate the set of classes which should receive a given formatting. E.g., cout << punctuate< vector<string> >("[", ",", "]") << punctuate< vector<_> >("{", ",", "}"); The above code tells std::cout to format vectors of strings with square brackets but all other vectors with curly brackets. I wanted to treat vector<_> and vector<_, _> as equlivalent, so I wrote a metafunction rebind which takes a template specialization T<P1, ..., Pn> and returns T<_, ..., _>. Using your library, I would need to use an mpl iteration construct to implement this templa te, and would also need to discover the arity of T (using mpl::aux::template_arity). A much more efficient and straightforward solution is to use a sequence of partial specializations, one for each arity. The moral is that rebind should be able to rebind several template arguments at once. 2) For another yet-to-be posted library, I implemented a generic facility for chaining user-defined policies to avoid increased instance size resulting from multiple inheritance. (See http://www.boost.org/libs/utility/operators.htm#chaining http://www.cuj.com/documents/s=8890/cujexp0310alexandr/alexandr.htm ) The convention is that user-defined policies should be templates whose last argument position is reserved for another policy, from which the user-defined policy should derive. Now, given two policies P1 and P2, we can combine them as follows: (i) if P1 is not a template instance (shame on the user!), return a policy which derives indirectly from both P1 and P2. (ii) if P1 is a template specialization of the form T<Arg1, ...., Arg(n-1), empty_base>, return T<Arg1, ...., Arg(n-1), P2> (iii) otherwise, if P1 is a template specialization of the form T<Arg1, ...., Argn>, return T< Arg1, ..., combine<Argn, P2> > Again, this is fairly straightforward to implement as a sequence of partial specializations (two for each arity, this time), but your metafunction doesn't help much. --- I'm not sure there is a general solution to problems like the above, but I'd be interested to see If you can come up with one. > I have tested the code using MSVC 7.1 and GCC 3.3.2-1. Have you tested it with templates that have default template arguments? GCC notoriously will allow std::vector<char> to match the partial specialization template<template<typename> class T, typename P> struct foo< T<P> > { /* ... */ }; despite the fact that std::vector is a binary template. > Kind Regards, > James Harris. Jonathan
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk