Topic: typeof?


Author: "Mycroft Holmes" <holmes@technologist.REMOVEME.com>
Date: Sat, 27 Oct 2001 09:11:45 GMT
Raw View
Suppose I want to write a template function which calls some fixed.name
method of the template-parameter class.
(idiot) example: return the first object in a generic container.

template <typename GenericContainer>
xxxxxx getFirstObject(const GenericContainer& gc)
{
    return *gc.begin();
}

how do I deduce the 'xxxxxx' type?
Obviously it's known at compile time, because whenever the compiler checks
IF GenericContainer has some method .begin(), it also knows its return type.
But what do I write instead of the x's?

Of course the example is not 100% suitable, because IF YOU USE ONLY PURE STL
CONTAINERS you could set
xxxxxx = GenericContainer::value_type
and this should go.

But the general problem is unsolved; is there some 'typeof(...)' operator?
--
 The set of solutions is never empty.
 Two solutions together form a new problem.
-- Mycroft Holmes


---
[ 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: Andre Stein <stone@steinsoft.net>
Date: Sat, 27 Oct 2001 09:54:33 GMT
Raw View
Hi,

there is something like a typeof operator. The operator
is called typeid(..) and returns a constant reference
to a type_info class. This class holds the name of the class
and lets you compare two classes.

Here is a little example how to use it:

//!!!Important!!!
#include <typeinfo.h>
#include <iostream.h>

int main()
{
  char test;
  char test2;

  cout << "Has test the same type as test2??" << endl;
  cout << (typeid(test) =3D=3D typeid(test2)) << endl; // Result =3D true
  //Display name of test's type
  cout << "Type of test : " << typeid(test).name() << endl;

  return 0;
}

You can also use typeid for your own classes. Happy
Coding!!

Bye,
Andr=E9
------
http://www.steinsoft.net

Mycroft Holmes wrote:

> Suppose I want to write a template function which calls some fixed.name
> method of the template-parameter class.
> (idiot) example: return the first object in a generic container.
>=20
> template <typename GenericContainer>
> xxxxxx getFirstObject(const GenericContainer& gc)
> {
>     return *gc.begin();
> }
>=20
> how do I deduce the 'xxxxxx' type?
> Obviously it's known at compile time, because whenever the compiler che=
cks
> IF GenericContainer has some method .begin(), it also knows its return =
type.
> But what do I write instead of the x's?
>=20
> Of course the example is not 100% suitable, because IF YOU USE ONLY PUR=
E STL
> CONTAINERS you could set
> xxxxxx =3D GenericContainer::value_type
> and this should go.
>=20
> But the general problem is unsolved; is there some 'typeof(...)' operat=
or?
> --
>  The set of solutions is never empty.
>  Two solutions together form a new problem.
> -- Mycroft Holmes
>=20
>=20
> ---
> [ 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               =
 ]
>=20
>=20

---
[ 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: jeremy@jdyallop.freeserve.co.uk (Jeremy Yallop)
Date: Sat, 27 Oct 2001 10:07:21 GMT
Raw View
Mycroft Holmes (holmes@technologist.REMOVEME.com) wrote in comp.lang.c++:
>Suppose I want to write a template function which calls some fixed.name
>method of the template-parameter class.
>(idiot) example: return the first object in a generic container.
>
>template <typename GenericContainer>
>xxxxxx getFirstObject(const GenericContainer& gc)
>{
>    return *gc.begin();
>}
>
>how do I deduce the 'xxxxxx' type?
>Obviously it's known at compile time, because whenever the compiler checks
>IF GenericContainer has some method .begin(), it also knows its return type.
>But what do I write instead of the x's?

template <class T, template <class> class CONTAINER>
T getFirstObject(const CONTAINER<T>& cont)
{
  return cont.front();
}

>But the general problem is unsolved; is there some 'typeof(...)' operator?

No.

Jeremy.

---
[ 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: tom_usenet@hotmail.com (Tom)
Date: Sun, 28 Oct 2001 22:59:10 GMT
Raw View
On Sat, 27 Oct 2001 09:11:45 GMT, "Mycroft Holmes"
<holmes@technologist.REMOVEME.com> wrote:

>Suppose I want to write a template function which calls some fixed.name
>method of the template-parameter class.
>(idiot) example: return the first object in a generic container.
>
>template <typename GenericContainer>
>xxxxxx getFirstObject(const GenericContainer& gc)
>{
>    return *gc.begin();
>}
>
>how do I deduce the 'xxxxxx' type?
>Obviously it's known at compile time, because whenever the compiler checks
>IF GenericContainer has some method .begin(), it also knows its return type.
>But what do I write instead of the x's?
>
>Of course the example is not 100% suitable, because IF YOU USE ONLY PURE STL
>CONTAINERS you could set
>xxxxxx = GenericContainer::value_type
>and this should go.
>
>But the general problem is unsolved; is there some 'typeof(...)' operator?

Yes, if you are using g++. g++ includes it as an extension. It is
expected to make it into the next revision of the C++ standard (not
for a few years yet).

Tom

---
[ 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: "Mycroft Holmes" <holmes@technologist.REMOVEME.com>
Date: Mon, 29 Oct 2001 16:13:39 GMT
Raw View
> template <class T, template <class> class CONTAINER>
> T getFirstObject(const CONTAINER<T>& cont)
> {
>   return cont.front();
> }
>

thanks, but there must be something nonstandard in your function.
can you help me?
this does not compile:



#include <vector>
#include <stack>
#include <iostream>
using namespace std;

template <class T, template <class> class CONTAINER >
T getFirstObject(CONTAINER<T> cont)
{
 return cont.front();
}


int main(int argc, char* argv[])
{
 vector<double> v;
 v.push_back(5.0);

 stack<int> x;
 x.push(34);
 cout << getFirstObject(v) << endl;
 cout << getFirstObject(x) << endl;

 return 0;
}


Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
Copyright 1988-2001 Comeau Computing.  All rights reserved.
MODE:non-strict warnings C++

"14145.c", line 20: error: no instance of function template "getFirstObject"
          matches the argument list
            The argument types that you used are: (std::vector<double, std::allocator<double>>)
   cout << getFirstObject(v) << endl;
           ^

"14145.c", line 21: error: no instance of function template "getFirstObject"
          matches the argument list
            The argument types that you used are: (std::stack<int, std::deque<int,
                      std::allocator<int>>>)
   cout << getFirstObject(x) << endl;
           ^

2 errors detected in the compilation of "14145.c".


--
 The set of solutions is never empty.
 Two solutions together form a new problem.
-- Mycroft Holmes




---
[ 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: Andrew Cady <please@no.spam>
Date: Mon, 29 Oct 2001 16:13:24 GMT
Raw View
"Mycroft Holmes" <holmes@technologist.REMOVEME.com> writes:

> Suppose I want to write a template function which calls some
> fixed.name method of the template-parameter class.  (idiot) example:
> return the first object in a generic container.
>
> template <typename GenericContainer>
> xxxxxx getFirstObject(const GenericContainer& gc)
> {
>     return *gc.begin();
> }
>
> how do I deduce the 'xxxxxx' type?

Standard containers define public typedefs for this sort of thing:

template <class C>
typename C::value_type front(const C& c) {
    return c.front();
} // Please don't name functions things like getFirstObject().
  // The standard library doesn't use such names, because they suck.

template <class C>
typename C::iterator begin(C& c) {
    return c.begin();
}

template <class C>
typename C::const_iterator begin(const C& c) {
    return c.begin();
}

The C++ Programming Language provides the full list, as (presumably)
would any STL reference.

You can use a second template parameter when such mechanisms are
unavailable (they should be available for containers, which should
implement the interface of the STL containers, but we can't always be
so lucky).

This isn't relevant on comp.std.c++; followups set to comp.lang.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                ]





Author: "Richard Smith" <richard@ex-parrot.com>
Date: Mon, 29 Oct 2001 17:36:31 GMT
Raw View
"Mycroft Holmes" <holmes@technologist.REMOVEME.com> wrote in message
news:WK9D7.180$7A4.9665@news.infostrada.it...
> > template <class T, template <class> class CONTAINER>
> > T getFirstObject(const CONTAINER<T>& cont)
> > {
> >   return cont.front();
> > }
> >
>
> thanks, but there must be something nonstandard in your function.
> can you help me?
> this does not compile:
>
>
>
> #include <vector>
> #include <stack>
> #include <iostream>
> using namespace std;
>
> template <class T, template <class> class CONTAINER >
> T getFirstObject(CONTAINER<T> cont)
> {
>  return cont.front();
> }
>
>
> int main(int argc, char* argv[])
> {
>  vector<double> v;
>  v.push_back(5.0);
>
>  stack<int> x;
>  x.push(34);
>  cout << getFirstObject(v) << endl;
>  cout << getFirstObject(x) << endl;
>
>  return 0;
> }


No, this isn't legal code, although I believe that gcc has a non-standard
extension to allow this. In your example, v is of type std::vector<double,
std::allocator<double> >.  To instantiate getFirstObject(v), you need to
bind std::vector (which is of type template<class, class> class) to the
second template parameter (which is only of type template<class> class).
The C++ standard doesn't allow the use of default template arguments whilst
binding template template parameters.

There have been a number of suggestions on these news groups for language
extentions that would make this possible.  One suggestion that I can recall
(I believe it was by Alexi Alexandrescu) was to allow template template
parameters of unspecified type.  For example, your getFirstObject function
would then be written,

    template <class T, template class CONTAINER >
    T getFirstObject(CONTAINER<T> cont)
    {
      return cont.front();
    }

Another solutions that can be done in today's language is to make a
container_traits class that defines the value_type, a container_category tag
and perhaps even a rebind<T>::other mechanism.

--
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: jeremy@jdyallop.freeserve.co.uk (Jeremy Yallop)
Date: Tue, 30 Oct 2001 18:18:22 GMT
Raw View
Richard Smith wrote in comp.std.c++:
>
>"Mycroft Holmes" <holmes@technologist.REMOVEME.com> wrote in message
>news:WK9D7.180$7A4.9665@news.infostrada.it...
>>
>> #include <vector>
>> #include <stack>
>> #include <iostream>
>> using namespace std;
>>
>> template <class T, template <class> class CONTAINER >
>> T getFirstObject(CONTAINER<T> cont)
>> {
>>  return cont.front();
>> }
>>
>>
>> int main(int argc, char* argv[])
>> {
>>  vector<double> v;
>>  v.push_back(5.0);
>>
>>  stack<int> x;

stack doesn't have a front() member function.

>>  x.push(34);
>>  cout << getFirstObject(v) << endl;
>>  cout << getFirstObject(x) << endl;
>>
>>  return 0;
>> }
>
>
>No, this isn't legal code, although I believe that gcc has a non-standard
>extension to allow this. In your example, v is of type std::vector<double,
>std::allocator<double> >.  To instantiate getFirstObject(v), you need to
>bind std::vector (which is of type template<class, class> class) to the
>second template parameter (which is only of type template<class> class).
>The C++ standard doesn't allow the use of default template arguments whilst
>binding template template parameters.

Could you provide a reference from the standard to support this?
In particular, is the following code legal?

   #include <vector>
   #include <set>

   using namespace std;

   template <class T, template<class> class C> class Xrefd {
       C<T>  mems;
       C<T*> refs;
       // ...
   };

   Xrefd<int, vector> x1;
   Xrefd<int, set>    x2;

   (adapted from 'The C++ Programming language, special edition',
                  p855, section C.13.3)

>There have been a number of suggestions on these news groups for language
>extentions that would make this possible.  One suggestion that I can recall
>(I believe it was by Alexi Alexandrescu) was to allow template template
>parameters of unspecified type.  For example, your getFirstObject function
>would then be written,
>
>    template <class T, template class CONTAINER >
>    T getFirstObject(CONTAINER<T> cont)
>    {
>      return cont.front();
>    }
>
>Another solutions that can be done in today's language is to make a
>container_traits class that defines the value_type, a container_category tag
>and perhaps even a rebind<T>::other mechanism.

Another solution (for this simple case, at least) is:

   template <class T, class CONTAINER>
   void getFirstObject(const CONTAINER& cont, T& obj)
   {
      obj = cont.front();
   }

Jeremy.

---
[ 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: Tue, 30 Oct 2001 20:43:32 GMT
Raw View
"Jeremy Yallop" <jeremy@jdyallop.freeserve.co.uk> wrote in message
news:9rmgdn$uh4v4$1@ID-114079.news.dfncis.de...
> Richard Smith wrote in comp.std.c++:

[...]

> >No, this isn't legal code, although I believe that gcc has a non-standard
> >extension to allow this. In your example, v is of type
std::vector<double,
> >std::allocator<double> >.  To instantiate getFirstObject(v), you need to
> >bind std::vector (which is of type template<class, class> class) to the
> >second template parameter (which is only of type template<class> class).
> >The C++ standard doesn't allow the use of default template arguments
whilst
> >binding template template parameters.
>
> Could you provide a reference from the standard to support this?
> In particular, is the following code legal?
>
>    #include <vector>
>    #include <set>
>
>    using namespace std;
>
>    template <class T, template<class> class C> class Xrefd {
>        C<T>  mems;
>        C<T*> refs;
>        // ...
>    };
>
>    Xrefd<int, vector> x1;
>    Xrefd<int, set>    x2;
>
>    (adapted from 'The C++ Programming language, special edition',
>                   p855, section C.13.3)
>

The standard is ambiguous on this point, and 14.3.3 does not state how
argument matching for template template parameters is actually done.  This
was the subject to defect report #150
(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_closed.html#150) which asked
(amongst other things) whether these examples are legal.  This DR has been
rejected "not a defect" and the following rationale was given:

"Template template parameters are intended to be handled analogously to
function function parameters. Thus the number of parameters in a template
template argument must match the number of parameters in a template template
parameter, regardless of whether any of those paramaters have default
arguments or not. ..."

If you try the above code in Comeau 4.2.42.2, you get the following error

"8051.c", line 13: error: class template "std::vector" is not compatible
with
          template template parameter "C"
        Wild guess: C takes less parameters?
        Wild guess: Watch out for default template arguments (like
std::allocator)
  Xrefd<int, vector> x1;
             ^
which suggests to me that the authors of Comeau definately think that this
code is illegal.

Gcc 3.0.1 on the other hand compiles this code happily, and the following
comment in gcc/cp/pt.c suggests that at least one author thought it should
be legal:

/* [...]

   Consider the example:
     template <class T, class Allocator = allocator> class vector;
     template<template <class U> class TT> class C;

   C<vector> is a valid instantiation.  PARM_PARMS for the above code
   contains a TYPE_DECL (for U),  ARG_PARMS contains two TYPE_DECLs (for
   T and Allocator) and OUTER_ARGS contains the argument that is used to
   substitute the TT parameter.  */


So it seems that Stroustrup and gcc think that the code should be legal,
whilst Comeau and the standards committee think it shouldn't.  To be honest,
I think that given the evident confusion about how this should be handled,
the standard should be ammended to explicitly state which behaviour is
intended.

--
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: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Tue, 30 Oct 2001 17:24:22 CST
Raw View
"Richard Smith" <richard@ex-parrot.com> writes:

[...]

| Gcc 3.0.1 on the other hand compiles this code happily, and the following
| comment in gcc/cp/pt.c suggests that at least one author thought it should
| be legal:
|
| /* [...]
|
|    Consider the example:
|      template <class T, class Allocator = allocator> class vector;
|      template<template <class U> class TT> class C;
|
|    C<vector> is a valid instantiation.  PARM_PARMS for the above code
|    contains a TYPE_DECL (for U),  ARG_PARMS contains two TYPE_DECLs (for
|    T and Allocator) and OUTER_ARGS contains the argument that is used to
|    substitute the TT parameter.  */

The above code wasn't written with DR resolution in mind.

| So it seems that Stroustrup and gcc think that the code should be legal,
| whilst Comeau and the standards committee think it shouldn't.  To be honest,
| I think that given the evident confusion about how this should be handled,
| the standard should be ammended to explicitly state which behaviour is
| intended.

The DR resolution reflects the committee intent.  But, yes, I agree
with you such things are better clearly spelled out, unambigously.

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

---
[ 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: Wed, 31 Oct 2001 16:35:11 GMT
Raw View
Andrew Cady <please@no.spam> wrote in message news:<87vggzt8oe.fsf@homer.cghm>...
> "Mycroft Holmes" <holmes@technologist.REMOVEME.com> writes:
>
> > Suppose I want to write a template function which calls some
> > fixed.name method of the template-parameter class.  (idiot) example:
> > return the first object in a generic container.
> >
> > template <typename GenericContainer>
> > xxxxxx getFirstObject(const GenericContainer& gc)
> > {
> >     return *gc.begin();
> > }
> >
> > how do I deduce the 'xxxxxx' type?
>
> Standard containers define public typedefs for this sort of thing:

The example is presumably provided for illustration only. Here's
another one: write a function f such that f(p) is equivalent to *p,
for any p.

Even the original example presents some difficulties, though.

> template <class C>
> typename C::value_type front(const C& c) {
>     return c.front();
> }

The original example says *c.begin(), not c.front(). front() is an
optional sequence requirement, while begin() is a container
requirement. Furthermore, front() returns C::reference or
C::const_reference, depending on C's constness, not C::value_type.
Except that when C is std::set, a front() (if set had one) would
always return C::const_reference, because both set iterators are
constant.

>   // Please don't name functions things like getFirstObject().
>   // The standard library doesn't use such names, because they suck.

Perhaps. This doesn't really matter, though.

> template <class C>
> typename C::iterator begin(C& c) {
>     return c.begin();
> }
>
> template <class C>
> typename C::const_iterator begin(const C& c) {
>     return c.begin();
> }

Another very interesting problem presents itself here. For a const
container, the two overloads _may_ be ambiguous (this is an open
issue.) See

http://groups.google.com/groups?selm=3B0F73E9%40MailAndNews.com

and the associated thread.

> The C++ Programming Language provides the full list, as (presumably)
> would any STL reference.
>
> You can use a second template parameter when such mechanisms are
> unavailable (they should be available for containers, which should
> implement the interface of the STL containers, but we can't always be
> so lucky).
>
> This isn't relevant on comp.std.c++; followups set to comp.lang.c++.

Quite the opposite, I think. :-)

--
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                ]