Topic: Problem with template templates


Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Fri, 26 Jan 2001 23:56:50 GMT
Raw View
Say I want to provide access from the outside to a template parameter for
some template. Then I use the classic construct:

template <class T>
class Foo
{
    ...
    typedef T Bar;
};

Now I can access Foo's template parameter for a given instantiation SomeFoo
by writing 'SomeFoo::Bar,' appropriately garnished with 'typename.'

So far, so good. Now:

template <template <class> class T>
class Foo
{
    ...
    // ick, can't use typedef
};

The only solution I found was a tired one, based upon traits. And so I have
two questions:

1. Is it any easy solution to this that I am missing?

2. Is there any chance to give template template parameters some statute
that would render them actually useful?


Andrei


---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kuehl@ramsen.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: Sat, 27 Jan 2001 00:43:08 GMT
Raw View
Hi,
Andrei Alexandrescu (andrewalex@hotmail.com) wrote:
: 1. Is it any easy solution to this that I am missing?

  template <template <typename T> class Arg>
  struct foo {
    template <typename T> struct aux { typedef Arg<T> type; };
    // ...
  };

It is not ideal but I think you should be able to get access to arbitrary
intantiations of the template template argument using the 'aux' structure.
I'm not sure whether this is the solution you also had in mind but I don't
think it is that bad. On the other hand, I think you cannot do everything
with this approach...

: 2. Is there any chance to give template template parameters some statute
: that would render them actually useful?

I think they are indeed useful! Sure, template typedefs are really missing
but they can be kind of simulated with the above construct. What are you
missing when you are saything that template template parameters are not
actually useful?
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Kuyper <kuyper@wizard.net>
Date: Sat, 27 Jan 2001 00:43:00 GMT
Raw View
Andrei Alexandrescu wrote:
>
> Say I want to provide access from the outside to a template parameter for
> some template. Then I use the classic construct:
>
> template <class T>
> class Foo
> {
>     ...
>     typedef T Bar;
> };
>
> Now I can access Foo's template parameter for a given instantiation SomeFoo
> by writing 'SomeFoo::Bar,' appropriately garnished with 'typename.'
>
> So far, so good. Now:
>
> template <template <class> class T>
> class Foo
> {
>     ...
>     // ick, can't use typedef
> };
>
> The only solution I found was a tired one, based upon traits. And so I have
> two questions:
>
> 1. Is it any easy solution to this that I am missing?
>

One step in the right direction would be to use a templated typedef:

template <template <class> class T>
class Foo
{
 template < class X >
 class Name1
 {
  typedef T<X> Name2;
 };
};

(My apologies for the dummy names, but whenever I use this trick I have
a hard time coming up with suitable names.) Name1 and Name2 should be
chosen to go together, because they always will.

Example of use:
 Foo<std::vector>::Name1<T>::Name2

is the same as std::vector<T>.

Note: this doesn't give you the template itself, but only the template
specialized for a particular type. For some purposes, that will be
sufficient. For others, it won't be. Sorry.

> 2. Is there any chance to give template template parameters some statute
> that would render them actually useful?

I'm not sure what you're trying to say (stature?). However, I've found
very little use for them. That doesn't prove much; I earn my pay writing
C, not C++.

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Mon, 29 Jan 2001 18:16:49 GMT
Raw View
"Dietmar Kuehl" <kuehl@ramsen.informatik.uni-konstanz.de> wrote in message
news:94t4md$g51$3@news.BelWue.DE...
> Hi,
> Andrei Alexandrescu (andrewalex@hotmail.com) wrote:
> : 1. Is it any easy solution to this that I am missing?
>
>   template <template <typename T> class Arg>
>   struct foo {
>     template <typename T> struct aux { typedef Arg<T> type; };
>     // ...
>   };

Nah, that won't work for what I want. Consider:

template <template <typename T> class Arg>
struct foo {
    template <typename T> struct aux { typedef Arg<T> type; };
    // ...
};

template <template <typename T> class Arg>
struct bar {
};

Now I have in hand a type some_foo which I know is an instantiation of foo.
Cool. I need to instantiate the bar class template with the same template
template parameter as some_foo has. Not cool.

The solution I came up with is this:

namespace private_ // my coolest C++ idiom so far :o)
{
    template <class> struct bar_traits;
    template <template <typename> class Arg>
    struct bar_traits< foo<Arg> >
    {
        typedef bar<Arg> result;
    };
}

Now given some_foo I can obtain what I want by typing 'typename
private_::bar_traits<some_foo>::result'. Whew!

This application of traits is missing from my articles on traits, which I
hoped were reasonably complete :o).

You know that game "Street Fighter"? Same with C++. You walk through
problems, and no matter what problem appears, you kick it somehow :o).

> : 2. Is there any chance to give template template parameters some statute
> : that would render them actually useful?
>
> I think they are indeed useful! Sure, template typedefs are really missing
> but they can be kind of simulated with the above construct. What are you
> missing when you are saything that template template parameters are not
> actually useful?

I dunno. Recently, I worked with them intensively. Somehow things suddenly
become awkward when you start using template templates. In my opinion they
should be somehow given more symbolic weight, and be relieved of the rigid
binding they now have.


Andrei


---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: pdimov@techno-link.com
Date: Mon, 29 Jan 2001 18:17:05 GMT
Raw View
In article <94t2l4$etg0p$1@ID-14036.news.dfncis.de>,
  "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote:
> Say I want to provide access from the outside to a template parameter
for
> some template. Then I use the classic construct:
>
> template <class T>
> class Foo
> {
>     ...
>     typedef T Bar;
> };
>
> Now I can access Foo's template parameter for a given instantiation
SomeFoo
> by writing 'SomeFoo::Bar,' appropriately garnished with 'typename.'
>
> So far, so good. Now:
>
> template <template <class> class T>
> class Foo
> {
>     ...
>     // ick, can't use typedef
> };

Sounds like a good argument for template typedefs. I'll remember it for
the time I finally get to writing the formal extension proposal. (What
is the status of that famous Proposed Extensions List? Can I simply
post an article with the subject prefixed appropriately to get my
proposal on it?)

--
Peter Dimov
Multi Media Ltd.


Sent via Deja.com
http://www.deja.com/

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Valentin.Bonnard@free.fr (Valentin Bonnard)
Date: Tue, 30 Jan 2001 12:14:03 GMT
Raw View
> So far, so good. Now:
>
> template <template <class> class T>
> class Foo
> {
>
>     // ick, can't use typedef
> };
>
> The only solution I found was a tired one, based upon traits. And so I
have
> two questions:
>
> 1. Is it any easy solution to this that I am missing?

Here is a simple (but not so easy) solution; the most important
thing to consider is that it is generic.

The following C++ program uses template template parameters,
explicit class specialisation. (I first tried with explicit
function specialisation, but g++ did an ICE.)

#include <iostream>

// An injection from class templates to types
template <template <class> class U>
struct theT {};

// Some template templated class
template <template <class> class T>
class Foo
{
public:
  // export argument
  typedef theT<T> myT;
};

// Example of use

// Have different class templates to have something
// to instanciate Foo on

template <class T>
struct template_1 {};

template <class T>
struct template_2 {};

// ``Usefull'' stuff depending on which template we have
// instanciated Foo on

template <template <class> class T>
struct do_something_with_T {
  int operator()() {
    cout << "This is an unknown template";
    return 0;
  }
};

template <>
struct do_something_with_T<template_1> {
  int operator()() {
    cout << "This is an template 1";
    return 1;
  }
};

template <>
struct do_something_with_T<template_2> {
  int operator()() {
    cout << "This is an template 2";
    return 2;
  }
};

// This is the engine used by the frobnicate function

// Do not use this
template <class whichT>
struct frobnication { };

template <template <class> class whichT>
class use
{};

template <template <class> class whichT>
struct frobnication<theT<whichT> > {
  int operator ()()
  {
    return do_something_with_T<whichT> () ();
  }
};

// FooLike is the concept abstracting the Foo interface
template <class FooLike>
int frobnicate (FooLike)
{
  return frobnication<typename FooLike::myT> ()();
}

// Time to try it
int main ()
{
  cout << frobnicate (Foo<template_1> ()) << endl;
  cout << frobnicate (Foo<template_2> ()) << endl;
}

--
Valentin Bonnard

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Geurt Vos" <G.Vos@rohill.nl>
Date: Tue, 30 Jan 2001 07:39:38 CST
Raw View
> Nah, that won't work for what I want. Consider:
>
> template <template <typename T> class Arg>
> struct foo {
>     template <typename T> struct aux { typedef Arg<T> type; };
>     // ...
> };
>
> template <template <typename T> class Arg>
> struct bar {
> };
>
> Now I have in hand a type some_foo which I know is an instantiation of
foo.
> Cool. I need to instantiate the bar class template with the same template
> template parameter as some_foo has. Not cool.
>
> The solution I came up with is this:
>
> namespace private_ // my coolest C++ idiom so far :o)
> {
>     template <class> struct bar_traits;
>     template <template <typename> class Arg>
>     struct bar_traits< foo<Arg> >
>     {
>         typedef bar<Arg> result;
>     };
> }
>
> Now given some_foo I can obtain what I want by typing 'typename
> private_::bar_traits<some_foo>::result'. Whew!
>

Here's a unrealistic alternative, where the bar_traits class is basically
integrated into the foo class:

template <template <typename T> class Arg>
struct foo {
    template <template <template <typename> class> class templ>
    struct templ_traits {
        typedef templ<Arg> result;
    };
    // ...
};

The only real difference with your example is that this one will
work for any type, while the declartion didn't get any worse.
It's now [typename] some_foo::templ_traits<bar>::result

I don't know, is this called a template template template param?

I said 'unrealistic', because the general response of compilers to
this piece of code is 'internal compiler error'. Comeau's online
test didn't report errors, hence I assumed the code was right
(and it seems the standard doesn't prohibit it).

Geurt




---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Tue, 30 Jan 2001 23:07:11 GMT
Raw View
"Geurt Vos" <G.Vos@rohill.nl> wrote in message
news:oef659.svv.ln@svr004.rohill.nl...
> Here's a unrealistic alternative, where the bar_traits class is basically
> integrated into the foo class:
>
> template <template <typename T> class Arg>
> struct foo {
>     template <template <template <typename> class> class templ>
>     struct templ_traits {
>         typedef templ<Arg> result;
>     };
>     // ...
> };

I - WANT - A - JACK - DANIELS. MAKE - IT - DOUBLE.

:o)

After the drink, I find your solution quite commendable. Thanks very much!

> I said 'unrealistic', because the general response of compilers to
> this piece of code is 'internal compiler error'. Comeau's online
> test didn't report errors, hence I assumed the code was right
> (and it seems the standard doesn't prohibit it).

MWCW doesn't like it, either, though it doesn't spit an internal compiler
error. It's just an external one :o).

By the way, MWCW is quite a nice compiler. If it supported template friends
and the Conversion template (http://cuj.com/experts/1810/alexandr.html), I
wouldn't ask for much more from it.


Andrei


---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Rene van Oostrum <rene+gnus@cs.uu.nl>
Date: Wed, 31 Jan 2001 14:44:21 GMT
Raw View
  Andrei> I - WANT - A - JACK - DANIELS. MAKE - IT - DOUBLE.

Hmmm...

  float Andrei( double JackDaniels ) throw ( up );

:-)
Rene


======================================= MODERATOR'S COMMENT:
 RFD for a comp.std.c++.recovery, anyone?  :-)

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]