Topic: Template Template Arguments
Author: Allan_W@my-dejanews.com (Allan W)
Date: Wed, 31 Jul 2002 15:01:36 GMT Raw View
"Carl Daniel" <cpdaniel@pacbell.net> wrote
> "Greg Hickman" <greg.hickman@lmco.com> wrote
> > Section C.13.3 of TC++PL (3rd ed.) contains an example
> > very similar to the following:
> >
> > #include <vector>
> >
> > template<class T, template<class> class C> class Xrefd {
> > C<T> mems;
> > C<T*> refs;
> > };
> >
> > Xrefd<int, std::vector> x1;
> >
> > Is the above use of std::vector legal as the second template parameter?
> > Some compilers complain because the number of template arguments in
> > 'template<class> class C' differs from the number of arguments defined for
> > the std::vector template (in this case, std::vector has at least two
> > template arguments including the standard allocator).
>
> Sadly no, this is not legal code, according to the standard.
>
> >
> > Does the standard require that all arguments of a template
> > template parameter be specified, even those that have
> > defaults like std::allocator in the above case? If so,
> > doesn't it become impossible to write such code portably
> > given that implementers have the freedom to add their own
> > template arguments to their containers?
>
> IMO, the standard is overly strict in requiring that ALL template
> parameters must match for a template template argument to be legal.
> Unfortunately, the standard is very clear about this, and the
> committee has ruled it "not a defect" (although it could possibly
> be an extension in a future rev of the standard). Let's hope this
> is changed some day - template template parameters are nearly
> useless as is.
I haven't tried this, but shouldn't this work?
// Original definition of Xrefd unchanged
template<class T, template<class> class C> class Xrefd {
C<T> mems;
C<T*> refs;
};
// Intermediate class identical to std::vector
// (except for Koenig lookup?)
template<class C>class VectorWithOneTemplateArg
: public std::vector<C> {};
// Now use that to instantiate Xrefd
Xrefd<int, VectorWithOneTemplateArg> x1;
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Wed, 31 Jul 2002 19:11:02 GMT Raw View
"Allan W" <Allan_W@my-dejanews.com> wrote in message
news:23b84d65.0207301723.d05faef@posting.google.com...
> I haven't tried this, but shouldn't this work?
>
> // Original definition of Xrefd unchanged
> template<class T, template<class> class C> class Xrefd {
> C<T> mems;
> C<T*> refs;
> };
>
> // Intermediate class identical to std::vector
> // (except for Koenig lookup?)
> template<class C>class VectorWithOneTemplateArg
> : public std::vector<C> {};
>
> // Now use that to instantiate Xrefd
> Xrefd<int, VectorWithOneTemplateArg> x1;
It will work, but it has two serious drawbacks: First, you have to
reproduce all the constructors of the base class in the derived class.
Consequently, you can't use a single template to adapt any client - rather,
you must have a VectorWithOneTemplateArg<T>, DequeWithOneTemplateArg<T>,
etc. Second, it's generally advised that you NOT derive from the standard
containers, as they're not designed to work as base classes (no virtual
destructor, etc).
Still, it's probably workable for many real-world situations.
-cd
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: agurtovoy@meta-comm.com (Aleksey Gurtovoy)
Date: Thu, 1 Aug 2002 21:47:52 GMT Raw View
Carl Daniel wrote in message news:<7jh19.35541$DA3.95216770@newssvr21.news.prodigy.com>...
> > #include <vector>
> >
> > template<class T, template<class> class C> class Xrefd {
> > C<T> mems;
> > C<T*> refs;
> > };
> >
> > Xrefd<int, std::vector> x1;
> >
> > Is the above use of std::vector legal as the second template parameter?
> > Some compilers complain because the number of template arguments in
> > 'template<class> class C' differs from the number of arguments defined for
> > the std::vector template (in this case, std::vector has at least two
> > template arguments including the standard allocator).
>
> Sadly no, this is not legal code, according to the standard.
[...]
> IMO, the standard is overly strict in requiring that ALL template parameters
> must match for a template template argument to be legal. Unfortunately, the
> standard is very clear about this, and the committee has ruled it "not a
> defect" (although it could possibly be an extension in a future rev of the
> standard). Let's hope this is changed some day - template template
> parameters are nearly useless as is.
Actually, as it was pointed by Nathan Myers about five years ago :),
even if the template template arguments' matching rules were more
relaxed, it would only partially solve the problem. Yes, you would be
able to write
Xrefd<int, std::vector> x1;
but what if you want to pass there a vector with a special allocator
instead?
We don't even have a built-in notation for that, expect of, may be,
forthcoming (?) template typedefs, if they are going to work this way:
template< typename T > std::vector<T,special_allocator> tmp_vector;
Xrefd<int, tmp_vector> x1;
It's still smells much like a workaround, IMO.
Ideally, one would like to write something like this instead:
Xrefd<int, std::vector<_,special_allocator> > x1;
where '_' (underscore) is a placeholder notation for the template
arguments to be filled in yet. The OP's example could be re-written
like this:
Xrefd<int, std::vector<_> > x1;
An exciting thing about the above is that you can already write this
kind of code - without altering the standard, waiting for template
typedefs to come to existance, etc. All you need for that is MPL's
lambda facility (http://www.mywikinet.com/mpl/paper/mpl_paper.html#lambda):
template<class T, class C> class Xrefd {
typedef typename mpl::lambda<C>::type c_;
typename mpl::apply<c_,T>::type mems; // C<T> mems;
typename mpl::apply<c_,T*>::type refs; // C<T*> refs;
};
That's all; now both of the above examples are perfectly valid C++ :).
The only remaining thing is to introduce users of 'Xrefd' class to the
lambda notation ;).
Aleksey
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Greg Hickman <greg.hickman@lmco.com>
Date: Mon, 29 Jul 2002 19:38:10 GMT Raw View
Section C.13.3 of TC++PL (3rd ed.) contains an example very similar to the
following:
#include <vector>
template<class T, template<class> class C> class Xrefd {
C<T> mems;
C<T*> refs;
};
Xrefd<int, std::vector> x1;
Is the above use of std::vector legal as the second template parameter?
Some compilers complain because the number of template arguments in
'template<class> class C' differs from the number of arguments defined for
the std::vector template (in this case, std::vector has at least two
template arguments including the standard allocator).
Does the standard require that all arguments of a template template
parameter be specified, even those that have defaults like std::allocator in
the above case? If so, doesn't it become impossible to write such code
portably given that implementers have the freedom to add their own template
arguments to their containers?
Thanks,
Greg Hickman
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Mon, 29 Jul 2002 21:36:15 GMT Raw View
"Greg Hickman" <greg.hickman@lmco.com> wrote in message
news:ai45ah$g5d2@cui1.lmms.lmco.com...
> Section C.13.3 of TC++PL (3rd ed.) contains an example very similar to the
> following:
>
> #include <vector>
>
> template<class T, template<class> class C> class Xrefd {
> C<T> mems;
> C<T*> refs;
> };
>
> Xrefd<int, std::vector> x1;
>
> Is the above use of std::vector legal as the second template parameter?
> Some compilers complain because the number of template arguments in
> 'template<class> class C' differs from the number of arguments defined for
> the std::vector template (in this case, std::vector has at least two
> template arguments including the standard allocator).
Sadly no, this is not legal code, according to the standard.
>
> Does the standard require that all arguments of a template template
> parameter be specified, even those that have defaults like std::allocator
in
> the above case? If so, doesn't it become impossible to write such code
> portably given that implementers have the freedom to add their own
template
> arguments to their containers?
IMO, the standard is overly strict in requiring that ALL template parameters
must match for a template template argument to be legal. Unfortunately, the
standard is very clear about this, and the committee has ruled it "not a
defect" (although it could possibly be an extension in a future rev of the
standard). Let's hope this is changed some day - template template
parameters are nearly useless as is.
>
> Thanks,
> Greg Hickman
-cd
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]