Topic: typedef for partial template specialization alias


Author: "Richard Smith" <richard@ex-parrot.com>
Date: Wed, 5 Sep 2001 16:49:34 GMT
Raw View
"Peter Dimov" <pdimov@mmltd.net> wrote in message
news:7dc3b1ea.0109030407.262e05ce@posting.google.com...
> "Richard Smith" <richard@ex-parrot.com> wrote in message
news:<999277417.10339.0.nnrp-13.3e31d362@news.demon.co.uk>...
>

 [...]

> > 3) A typedef specialisation of a class:
> >
> >     template <class T, class U> struct foo {};
> >     template <class T> typedef T foo<T, T> ;
>
> Ill-formed. You can't redefine the meaning of a class template via a
> typedef, templated or not:

I agree that this would require a more major change to the language, and I'm
not suggesting that it would be an advisable change to make.  (In fact I
think it would be a bad change for the reasons I gave in my earlier post.)
However, I think that it would probably be technincally feasible to allow
this construct via a typedef, templated or otherwise.  It is a language
feature that I have seen requested on this newsgroup and on c.l.c++.m and it
seemed worth mentioning it.

> The only case where a typedef template would be intechangeable with a
> class template is when matching a template parameter:
>
> template<template<class> class T> void f();
>
> f<std::vector>(); // error

Personally, I would be strongly in favour of allowing the default allocator
argument to be used to bind to this.  The usual objection that is raised
against this suggestion is the analogy with function default arguments;
however, I think that this is a case where the analogy is being stretched
too far.

In the code,

int fish(int (*fn)(int))
{
    return (*fn)(42);
}

the compiler doesn't know anything about the function *fn, and has to call
it assuming that it takes just one argument.  However, in the code,

template <template <class> class T>
class fish
{
    void soup()
    {
        T<int> t;
        // ...
    }
};

the compiler must know what the template T is before it can call instantiate
the function fish::soup, and so it will know about any default arguments of
T.

> template<class T> typedef std::vector<T> vector;
>
> f<vector>(); // ok

But I think that this is encouraging an overly verbose coding style.  For
example,

template<template<class, class> class T> void f();

f<std::vector>();  // Not portable.  std::vector might have more that two
template parameters

template <class T, class A> typedef std::vector<T, A> vector;
f<vector>();  // Portable, but verbose.

Requiring the use of this typedef to make the code portable seems to me to
be completely unnecessary, especially since in the vast majority of cases,
std::vector does only take two template parameters, and it is superfluous.


The main subtlety that I can see with this is making sure that no (legal)
existing code would break.  For example, suppose my STL defines vector as:

template <class T, class Alloc = allocator<T>, int blocksize = 32>
class vector;

Currently, if I have a pair of overloaded functions

template <template <class, class> class V, class T, class A>
void f(const V<T, A> &);

template <template <class, class, int> class V, class T, int I>
void f(const V<T, A, I> &);

then,

std::vector<int> foo;
f(foo);

should call the latter function.  (Although after a brief look at a few
various compilers, I've only seen Comeau that gets this right.)  Any changes
to the rules for binding template template parameters should still prefer
the latter function to the former, but I think that this could be
accomodated.

--
Richard Smith


---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 6 Sep 2001 17:40:53 GMT
Raw View
"Richard Smith" <richard@ex-parrot.com> wrote in message news:<999686423.12265.0.nnrp-13.3e31d362@news.demon.co.uk>...
> "Peter Dimov" <pdimov@mmltd.net> wrote in message
> news:7dc3b1ea.0109030407.262e05ce@posting.google.com...
> > The only case where a typedef template would be interchangeable with a
> > class template is when matching a template parameter:
> >
> > template<template<class> class T> void f();
> >
> > f<std::vector>(); // error
>
> Personally, I would be strongly in favour of allowing the default allocator
> argument to be used to bind to this.

This is a separate issue; I was simply saying that a typedef template
can get around the problem.

> > template<class T> typedef std::vector<T> vector;
> >
> > f<vector>(); // ok
>
> But I think that this is encouraging an overly verbose coding style.  For
> example,
>
> template<template<class, class> class T> void f();
>
> f<std::vector>();  // Not portable.  std::vector might have more that two
> template parameters

No, see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#94.
std::vector must have two template parameters.

--
Peter Dimov
Multi Media Ltd.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Richard Smith" <richard@ex-parrot.com>
Date: Fri, 7 Sep 2001 16:41:47 GMT
Raw View
"Peter Dimov" <pdimov@mmltd.net> wrote in message
news:7dc3b1ea.0109060401.2c05a3e5@posting.google.com...
> "Richard Smith" <richard@ex-parrot.com> wrote in message
news:<999686423.12265.0.nnrp-13.3e31d362@news.demon.co.uk>...
> > "Peter Dimov" <pdimov@mmltd.net> wrote in message
> > news:7dc3b1ea.0109030407.262e05ce@posting.google.com...
> > > template<class T> typedef std::vector<T> vector;
> > >
> > > f<vector>(); // ok
> >
> > But I think that this is encouraging an overly verbose coding style.
For
> > example,
> >
> > template<template<class, class> class T> void f();
> >
> > f<std::vector>();  // Not portable.  std::vector might have more that
two
> > template parameters
>
> No, see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#94.
> std::vector must have two template parameters.

Oh, OK.  I didn't realise they'd come to a decision about this yet.

--
Richard Smith


---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Richard Smith" <richard@ex-parrot.com>
Date: Fri, 31 Aug 2001 21:37:16 GMT
Raw View
"Sean Kelly" <kensai@pacbell.net> wrote in message
news:721ff0b.0108301120.11ec1b9f@posting.google.com...
> Currently, it is only possible to use typedef to alias fully defined
> template classes.  I'd like a way to alias partial specializations
> without subclassing and the overhead a virtual dtor requires.  That
> is, something like this:
>
> template<class T, class U>
> struct foo {
>
> };
>
> template<class T>
> typedef foo<T,int> sfoo;
>
> ...
>
> // these definitions are the same
> foo<char,int> f1;
> sfoo<char>    f2;


There was a quite detailed discussion on this idea on
comp.lang.c++.moderated in Oct/Nov 1999 under the subject line "templated
typedefs"; you might want to have a look at that.  In particular there was a
good discussion in a post by Christopher Eltschka [http://groups.google.com/
groups?hl=en&safe=off&rnum=17&selm=3829ABFB.64521D41%40physik.tu-muenchen.de
]
on how this would interact with partial specialisation.

I can think of three situations that templated typedefs could conceivably be
used:

1) A basic templated typedef, as in your example.

    template <class T, class U> struct foo {};
    template <class T> typedef foo<T, int> sfoo;

    sfoo<char> is the same type as foo<char, int>.

As far as I'm concerned, this would be a thoroughly good thing, and I hope
it makes it into C++0x.


2) A specialisation (partial or complete) of a templated typedef:

    template <class T> typedef const T *sfoo<T *>;

    sfoo<char> is the same type as foo<char, int>.
    sfoo<wchar_t *> is the same type as const wchar_t *.

I think that complete specialisation of templated typedef is a must.  One
important thing that I'd like to be able to do with a templated typedef
is:
    template <> typedef signed char integer<8>;
    template <> typedef short integer<16>;
    // ...

Partial specialisation would be nice, and the post that I mentioned above
had a possible algorithm that a compiler could use to handle overload
resolution in the presence of them.


3) A typedef specialisation of a class:

    template <class T, class U> struct foo {};
    template <class T> typedef T foo<T, T> ;

    foo<char, char> is the same type as char.
    sfoo<int> is the same type as int.
        (using the typedef class specialisation)
    sfoo<int *> is the same type as const int *.
        (using the typedef specialisation)

I suppose that if were to be possible to specialised a class with a
typedef, it would be logical to allow typedefs to be specialised
with a class:

    template <> class sfoo<float> {};

I would hope that any template typedef extenstion to the language would
stop short of allowing this.  This sort of construct would blur the
distinction
between a real types and and typedef aliases for them, and would probably
end up producing unmaintainable code.  I can only think of one occasion
when I've ever wanted to do this, which was in some legacy code that used
a non-STL allocator, that I wanted to be able to transparently use in STL
containers:

    namespace std
    {
        template <class T, int I>
        typedef vector< T, wrapper_allocator<T, I> >
            vector< T, non_stl_allocator<I> >;
    }

But even this probably wouldn't have worked (what about the vector's
constructors that take allocator objects?), and anyhow, there are
perfectly good, if slighly more verbose, ways of doing this in C++98.


--
Richard Smith


---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Tue, 4 Sep 2001 17:31:33 GMT
Raw View
"Richard Smith" <richard@ex-parrot.com> wrote in message news:<999277417.10339.0.nnrp-13.3e31d362@news.demon.co.uk>...

[on typedef templates]

The key to understanding typedef templates is to mentally rewrite

template<args> typedef expr id opt-args;

as

template<args> struct __typedef_id opt-args
{
  typedef expr type;
};

and later

id<args>

as

[typename] __typedef_id<args>::type.

> I can think of three situations that templated typedefs could conceivably be
> used:
>
> 1) A basic templated typedef, as in your example.
>
>     template <class T, class U> struct foo {};
>     template <class T> typedef foo<T, int> sfoo;

Fine.

> 2) A specialisation (partial or complete) of a templated typedef:
>
>     template <class T> typedef const T *sfoo<T *>;
>
>     sfoo<char> is the same type as foo<char, int>.
>     sfoo<wchar_t *> is the same type as const wchar_t *.

Fine as well.

>     template <> typedef signed char integer<8>;
>     template <> typedef short integer<16>;

Also fine:

template<> struct __typedef_integer<8>
{
  typedef signed char type;
}

> 3) A typedef specialisation of a class:
>
>     template <class T, class U> struct foo {};
>     template <class T> typedef T foo<T, T> ;

Ill-formed. You can't redefine the meaning of a class template via a
typedef, templated or not:

typedef int foo<int, int>; // error

Or to apply our rewriting rules:

template<class T> struct __typedef_foo<T, T>
{
  typedef T type;
};

Error, no __typedef_foo primary template has been defined.

The only case where a typedef template would be intechangeable with a
class template is when matching a template parameter:

template<template<class> class T> void f();

f<std::vector>(); // error

template<class T> typedef std::vector<T> vector;

f<vector>(); // ok

--
Peter Dimov
Multi Media Ltd.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: kensai@pacbell.net (Sean Kelly)
Date: Thu, 30 Aug 2001 19:57:07 GMT
Raw View
Currently, it is only possible to use typedef to alias fully defined
template classes.  I'd like a way to alias partial specializations
without subclassing and the overhead a virtual dtor requires.  That
is, something like this:

template<class T, class U>
struct foo {

};

template<class T>
typedef foo<T,int> sfoo;

...

// these definitions are the same
foo<char,int> f1;
sfoo<char>    f2;


Sean


(I apologize for posting from deja... it's all I can access from work)

---
[ 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.research.att.com/~austern/csc/faq.html                ]