Topic: typeof


Author: celtschk@Physik.TU-Muenchen.DE (Christopher Eltschka)
Date: Sat, 10 Feb 2001 11:43:40 GMT
Raw View
pdimov@techno-link.com writes:

>In article <hinnant-0602012058470001@syr-24-24-13-166.twcny.rr.com>,
>  hinnant@anti-spam_metrowerks.com (Howard Hinnant) wrote:
>> In article <95p0mb$2ti$1@nnrp1.deja.com>, pdimov@techno-link.com
>wrote:
>>
>> | I wonder how they respond to
>> |
>> | int const i = 1; __typeof__(i);
>> |
>> | and
>> |
>> | int & f(); __typeof__(f());
>> |
>> | A typeof that strips cv-qualifiers and doesn't distinuish l- from r-
>> | values is less "powerful." Expression template libraries need the
>more
>> | powerful version, since
>> |
>> | arg1 << 4
>> |
>> | must generate a function object whose return type may be a
>reference to
>> | the first argument (when called with std::cout.)
>>
>> MWCW 6.0 hits half of what you ask for:

>[...]

>> Output:
>>
>> i is a const int
>> f() is a int

>Unfortunately, the missing half is important. :-)

>I'll have to think about whether int & f() and int f() can be
>distinguished given this __typeof__ semantics.

>FWIW, here's my proposed typeof:

>typeof(expr) on an lvalue returns T &, where T is deduced from

>template<class T> void __f(T &);

>__f(expr);

>typeof(expr) on an rvalue returns plain T.

>In the example above typeof(i) would return int const &.

>It's easy to get the other typeof variants from this one, but not vice
>versa.

I don't like this.

I do, however, think that cv qualifiers should be preserved.
gcc doesn't do it (at least it didn't in 2.7.2, after that I
haven't tried again), and I was quite surprised when I found out
that the following did not compile:

int const i = 1;
typeof(i)* j = &i;

After all, you should be able to initialize a pointer to the
type of i with the address of i.

With your proposal, even removing the const from the int wouldn't
work, since you cannot write a pointer to a reference.

However, there's a better way to do all of this:

If you allow the syntax

  (expression)::member

to access members of the type of the expression (where expression
is not evaluated), then everyone can have "his" typeof:

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

template<class T> type<T> gcc(T const volatile&);
template<class T> type<T> MW(T&);

#define gcc_typeof(expr) (gcc(expr))::type
#define MW_typeof(expr) (MW(expr))::type

This has several advantages:

- There are two incompatible typeof's already; whatever the
  next standard might define as typeof would break at least
  one of them. This extension would break none

- The feature to access type members of expressions has been
  asked for several times independantly from typeof (although
  of course typeof could be used to do just this, too)

- This extension doesn't need a new keyword

---
[ 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: mbartosik@my-deja.com
Date: Mon, 12 Feb 2001 11:04:52 CST
Raw View
I've got a few points here, so I've posted to the root of the thread...

Point 1>
Preserving the whole type is essential. Especially in cases where a
variable must be cloned, and passed to a function. Failure to preserve
the type would give overloading/lookup problems.

e.g.

void foo(const int &);
void foo(int &);

int main()
{
   const int i = 0;
   typeof(i) j;

   foo(i); // These must call the same function
   foo(j); //
}

Point 2> Following up on Christopher Eltschka's suggestion:
>   If you allow the syntax
>
>   (expression)::member
>
>   to access members of the type of the expression (where expression
is not evaluated), then everyone can have "his" typeof:

To add more detail to Christopher's suggestion we could add something
like the following:

namespace std
{
   template<class T> struct _type
   {
      typedef T type;
   };

   template<typename T> _type<T>       same_type(T);
   template<typename T> _type<T>       non_const_type(const T);
   template<typename T> _type<const T> const_type(T);
   // support for volatile omitted for brevity
}

int i;
const int j;

(std::same_type(i))::type     clone_of_i(i);  // type is int

(std::same_type(i))::type     i2;     // type is int - most common use
(std::non_const_type(i)::type i3;     // type is int
(std::const_type(i)::type     i4;     // type is const int

(std::same_type(j))::type     i5;     // type is const int
(std::non_const_type(j)::type i6;     // type is int
(std::const_type(j)::type     i7;     // type is const int

The biggest problem with this is brevity. Without greater brevity than
this the pre-processor will be used:

#define __same_type(exp) (std::same_type(exp))::type

with usage
   int i;
   __same_type(i) clone_of_i(i);

This would be close to a keyword, but has none advantages of a keyword.
However it does have merit in that you can always locally #undef a
macro if you don't want it.

The important case for brevity is the common case. When you need the
exact same type. Any use of the preprocessor makes me uneasy, but
without addition of a keyword, I cannot see any other to maintain
brevity which is important for both acceptance and readability.

Point 3>
The places where I would most like to us some sort of typeof syntax are
where I have a declared a complex type e.g.
   std::map<int, std::string>
but I don't wish to use a typedef with a name based on the type e.g.
   typedef std::map<int, std::string> int_to_string_t;
and I don't wish to use a typedef with a name based on the use e.g.
   typedef std::map<int, std::string> employee_number_to_name_t

I don't want to use the former because it is too tidied to the type, if
I was to change the type of the typedef I would probably feel the need
to change the alias also.

I don't want to use the later because I end up with a new type for
almost very non-trivial variable. But worse name1_t could be the same
type as name2_t, and that can be a little misleading.

Point 4>
In the case of a lexicographically short type e.g. int,
std::vector<int>
I don't have a problem repeating the type long-hand, but with
std::map<int, std::string>::const_iterator
I start to feel like I need a 300 character wide screen.
In this case neither of the typedef solutions are ideal. It is mostly a
matter of readability rather than typing.

I have also noticed amongst my piers that most like short names.
It is hard enough to convince my piers of the merits of typing 'std::'
when they can just add
using namespace std;
If std:: was used in print more (yes I know the issues) there might be
less resistance.


So any solution must be short and clear.


Point 5>
I have been wishing for a 'typeof' syntax for at least three years now.
I was (maybe) going to ask Francis about it at the next ACCU
conference.
I nearly asked him a couple of years ago, but most language changes are
shot down so easily, and I thought that I needed more experience first.


Mark Bartosik
   member ACCU


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: pdimov@techno-link.com
Date: Mon, 12 Feb 2001 19:08:41 GMT
Raw View
In article <9616c3$4af$1@wsc10.lrz-muenchen.de>,
  celtschk@Physik.TU-Muenchen.DE (Christopher Eltschka) wrote:
> pdimov@techno-link.com writes:
>
> >FWIW, here's my proposed typeof:
>
> >typeof(expr) on an lvalue returns T &, where T is deduced from
>
> >template<class T> void __f(T &);
>
> >__f(expr);
>
> >typeof(expr) on an rvalue returns plain T.
>
> >In the example above typeof(i) would return int const &.
>
> >It's easy to get the other typeof variants from this one, but not
vice
> >versa.
>
> I don't like this.

Well, like it or not, this is "the" typeof that is needed to support
expression templates, since it preserves all the information.

The 'syntactic sugar' kind of typeof is, admittedly, more useful when
you just want to do

typeof(c)::iterator i = c.begin();

(which is wrong, by the way. :-))

I think that

let i = c.begin();

would be better.

> I do, however, think that cv qualifiers should be preserved.
> gcc doesn't do it (at least it didn't in 2.7.2, after that I
> haven't tried again), and I was quite surprised when I found out
> that the following did not compile:
>
> int const i = 1;
> typeof(i)* j = &i;
>
> After all, you should be able to initialize a pointer to the
> type of i with the address of i.
>
> With your proposal, even removing the const from the int wouldn't
> work, since you cannot write a pointer to a reference.

It's trivial to strip a reference. The syntax will be uglier, granted.
I see typeof as a low-level tool.

> However, there's a better way to do all of this:
>
> If you allow the syntax
>
>   (expression)::member

Probably a good idea, but I'll have to think about it in more detail.

> to access members of the type of the expression (where expression
> is not evaluated), then everyone can have "his" typeof:
>
> template<class T> struct type
> {
>   typedef T type;
> };
>
> template<class T> type<T> gcc(T const volatile&);

or just gcc(T)?

> template<class T> type<T> MW(T&);
>
> #define gcc_typeof(expr) (gcc(expr))::type
> #define MW_typeof(expr) (MW(expr))::type

Ok so far, but either way you lose the reference, if any.

To repeat: if I can't 'see' the reference on the return type, my
operator<< function object will return an ostream by value when called
with std::cout and 4. Not good.

--
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: pdimov@techno-link.com
Date: Wed, 7 Feb 2001 17:13:33 GMT
Raw View
In article <hinnant-0602012058470001@syr-24-24-13-166.twcny.rr.com>,
  hinnant@anti-spam_metrowerks.com (Howard Hinnant) wrote:
> In article <95p0mb$2ti$1@nnrp1.deja.com>, pdimov@techno-link.com
wrote:
>
> | I wonder how they respond to
> |
> | int const i = 1; __typeof__(i);
> |
> | and
> |
> | int & f(); __typeof__(f());
> |
> | A typeof that strips cv-qualifiers and doesn't distinuish l- from r-
> | values is less "powerful." Expression template libraries need the
more
> | powerful version, since
> |
> | arg1 << 4
> |
> | must generate a function object whose return type may be a
reference to
> | the first argument (when called with std::cout.)
>
> MWCW 6.0 hits half of what you ask for:

[...]

> Output:
>
> i is a const int
> f() is a int

Unfortunately, the missing half is important. :-)

I'll have to think about whether int & f() and int f() can be
distinguished given this __typeof__ semantics.

FWIW, here's my proposed typeof:

typeof(expr) on an lvalue returns T &, where T is deduced from

template<class T> void __f(T &);

__f(expr);

typeof(expr) on an rvalue returns plain T.

In the example above typeof(i) would return int const &.

It's easy to get the other typeof variants from this one, but not vice
versa.

--
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: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Mon, 5 Feb 2001 15:59:58 CST
Raw View
MWCW 6.0 has a __typeof__ keyword! Gnu has that, too.

I was wondering what is the feeling among the Standard C++ commitee - is
typeof likely to make it into the language, or not? If yes, when?


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: pedwards@dmapub.dma.org (Phil Edwards)
Date: Mon, 5 Feb 2001 23:16:36 GMT
Raw View
Andrei Alexandrescu <andrewalex@hotmail.com> wrote:
> MWCW 6.0 has a __typeof__ keyword! Gnu has that, too.
>
> I was wondering what is the feeling among the Standard C++ commitee - is
> typeof likely to make it into the language, or not? If yes, when?

There was an overall good feeling about it in the group two years ago.
Of the 130-odd messages that Deja hasn't managed to lose yet, the two that
I keep around are

    http://www.deja.com/=dnc/threadmsg_ct.xp?AN=511118145.1&mhitnum=12

and

    http://www.deja.com/=dnc/threadmsg_ct.xp?AN=511886873.1&mhitnum=16

The first article is a semi-proposal.  The second article is more humorous
than otherwise (I kept it primarily for the excellent nethack reference),
but it started off a good subthread.


Phil

--
pedwards at disaster dot jaj dot com  |  pme at sources dot redhat dot com
devphil at several other less interesting addresses in various dot domains
The gods do not protect fools.  Fools are protected by more capable fools.

---
[ 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: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 6 Feb 2001 11:10:54 GMT
Raw View
In article <95muqb$hrf0c$1@ID-14036.news.dfncis.de>, Andrei Alexandrescu
<andrewalex@hotmail.com> writes
>MWCW 6.0 has a __typeof__ keyword! Gnu has that, too.
>
>I was wondering what is the feeling among the Standard C++ commitee - is
>typeof likely to make it into the language, or not? If yes, when?

If yes, it won't be much before 2008. However it being in use in two
compilers will strengthen the case for it.


--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)

---
[ 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: "Ken Hagan" <K.Hagan@thermoteknix.co.uk>
Date: Tue, 6 Feb 2001 11:15:10 GMT
Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote...
> MWCW 6.0 has a __typeof__ keyword! Gnu has that, too.

Do they do it the same way?
Do they do it the same way as suggested by Hyman Rosen?
(Thanks for the link, Phil.)

2004 (or whenever it is) is long enough for vendors to establish
mutually incompatible language extensions, unless they conspire
to agree.

One of the reasons for forming a standard under the guidance of
the ISO was that it allows vendors to talk to each other without
risking criminal prosecution for monopoly practices. Are vendors
allowed to contribute to this thread?

---
[ 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: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Tue, 6 Feb 2001 11:50:01 GMT
Raw View
In article <newscache$kczb8g$pwj$1@firewall.thermoteknix.co.uk>, Ken
Hagan <K.Hagan@thermoteknix.co.uk> writes
>One of the reasons for forming a standard under the guidance of
>the ISO was that it allows vendors to talk to each other without
>risking criminal prosecution for monopoly practices. Are vendors
>allowed to contribute to this thread?

Well, I think ones who are members of a relevant National Standards body
are. We should sue the rest for stupidity:) and we should also charge
them royalties (OH, how I wish we could)

--
Francis Glassborow
See http://www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)

---
[ 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: hinnant@anti-spam_metrowerks.com (Howard Hinnant)
Date: Wed, 7 Feb 2001 15:49:51 GMT
Raw View
In article <95p0mb$2ti$1@nnrp1.deja.com>, pdimov@techno-link.com wrote:

| I wonder how they respond to
|
| int const i = 1; __typeof__(i);
|
| and
|
| int & f(); __typeof__(f());
|
| A typeof that strips cv-qualifiers and doesn't distinuish l- from r-
| values is less "powerful." Expression template libraries need the more
| powerful version, since
|
| arg1 << 4
|
| must generate a function object whose return type may be a reference to
| the first argument (when called with std::cout.)

MWCW 6.0 hits half of what you ask for:

#include <iostream>
#include <msl_utility>

int& f();

int main()
{
   using namespace Metrowerks;
   int const i = 1;
   std::cout << "i is a ";
   if (is_const<__typeof__(i)>::value)
      std::cout << "const ";
   if (is_integral<__typeof__(i)>::value)
      std::cout << "int";
   if (is_reference<__typeof__(i)>::value)
      std::cout << "&";
   std::cout << "\nf() is a ";
   if (is_const<__typeof__(f())>::value)
      std::cout << "const ";
   if (is_integral<__typeof__(f())>::value)
      std::cout << "int";
   if (is_reference<__typeof__(f())>::value)
      std::cout << "&";
}

Output:

i is a const int
f() is a int

-Howard

---
[ 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 <bonnardv@pratique.fr>
Date: 1997/12/05
Raw View
[I should redirect followups to comp.lang.c++.std.madness but
there isn't such a newsgroup, so I don't redirect followups.]

David Wragg <dpw@doc.ic.ac.uk> writes:

> amitp@Xenon.Stanford.EDU (Amit Patel) writes:
> >  Andrew Koenig <ark@research.att.com> wrote:
> >
> > >In the world of ordinary expressions, type declarations are
> > >necessary in the presence of overloading and nowhere else.
> > >Moreover, only built-in operators are overloaded.  But,
> > >for example, SML requires a type declaration here:
> > >
> > > fun sum(x, y) = x + y  (* illegal, no type specified *)
> > >
> > >because the compiler doesn't know whether you mean integer or real
> > >addition.  SML97 solves this problem a different way, by assuming
> > >integer addition.
> > >
> >
> > It seems like we lose overloading if we want type inference.
> >
>
> Doesn't SML only has overloaded built-in operators? There have been a
> number of type systems for functional languages proposed in which type
> inferencing and forms of overloading coexist more peacefully and are
> much more general than in SML. Haskell contains an example.

There is no question on the fact that you can built a system
with 'real' overloading, that is, overloading on partial
ordering of type matches (unlike Ada, which has 'stupid'
overloading based on type equivalence) and type inference
at the same time (in theory).

The basic idea is even simple (that is, to do it in a
silly way). You simply implement a backtracking overload
resolution: if a solution failed, find annother one. If
two solution matches, you fail, and backtrack or if you
can't the program is ill-formed.

The real question is: do you want to have that ?

foo (x, y)
{
    return x + y;
}

foo (x, y)
{
    return x * y;
}

foo (complex<float> (1, 2), 4); // ambiguous,
// complex<float> and int supports + and *

class T {
    operator* (argument); // accepts an arg of the same type
} x, y;

foo (x, y); // call the second foo, as there is no way to
// add x and y

Note that I assume that 'top-level' types, that is, types
of objects are known to do overload resolution.

bar (x)
{
    foo (x.a);
}

bar (x)
{
    foo (x.b);
}

struct U {
    int a;
    T b;
};
bar (U ());

Also note that you never know which function can be called.
In this case, as the first function would do an ambiguous
call foo (int, int), the second one is selected after
backtracking (as foo (T, T) clearly sellect the second foo).

BTW, you have to know how a function is written to call it.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: amitp@Xenon.Stanford.EDU (Amit Patel)
Date: 1997/11/27
Raw View
 Andrew Koenig <ark@research.att.com> wrote:

>In the world of ordinary expressions, type declarations are
>necessary in the presence of overloading and nowhere else.
>Moreover, only built-in operators are overloaded.  But,
>for example, SML requires a type declaration here:
>
> fun sum(x, y) = x + y  (* illegal, no type specified *)
>
>because the compiler doesn't know whether you mean integer or real
>addition.  SML97 solves this problem a different way, by assuming
>integer addition.
>

It seems like we lose overloading if we want type inference.

What ends up happening to me is that instead of being able to use the
same names for different kinds of types, I have to use different
names, often the full name with the type written in it:

 Overloading  ML

 function f(TYPE x) function f(x)
  op1(x)   TYPE.op1(x)
  op2(x)   TYPE.op2(x)
  op3(x)   TYPE.op3(x)

Instead of declaring the type of x, I have to name it for the
operations I do, so I end up writing the type in one form or another.

It also seems like overloading enhances generic programming, because a
function is applicable to more types of arguments if all those types
are allowed to share names of operations.  ML requires that you pass
the operations in explicitly, either by parameterizing on the module
or by passing in function arguments, and that's so inconvenient that I
don't make my functions as generic as I could.  :(


 - Amit
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: David Wragg <dpw@doc.ic.ac.uk>
Date: 1997/11/29
Raw View
amitp@Xenon.Stanford.EDU (Amit Patel) writes:
>  Andrew Koenig <ark@research.att.com> wrote:
>
> >In the world of ordinary expressions, type declarations are
> >necessary in the presence of overloading and nowhere else.
> >Moreover, only built-in operators are overloaded.  But,
> >for example, SML requires a type declaration here:
> >
> > fun sum(x, y) = x + y  (* illegal, no type specified *)
> >
> >because the compiler doesn't know whether you mean integer or real
> >addition.  SML97 solves this problem a different way, by assuming
> >integer addition.
> >
>
> It seems like we lose overloading if we want type inference.
>

Doesn't SML only has overloaded built-in operators? There have been a
number of type systems for functional languages proposed in which type
inferencing and forms of overloading coexist more peacefully and are
much more general than in SML. Haskell contains an example.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: skaller@zip.com.au (John (Max) Skaller)
Date: 1997/11/07
Raw View
On 01 Nov 97 15:08:36 GMT, ark@research.att.com (Andrew Koenig) wrote:
[better than typeof]

>I just have a hunch there's a much better solution out there,
>and that we should spend some time looking for it.

Of course, there IS a better solution, and it is well known:
it's called type inference. :-)

A  language like SML doesn't need ANY type declarations.
The type of everything is always known by the compiler.

This completely eradicates the need for template functions.
(Every function is _automatically_ generic)
The cost: NO automatic conversions. And also,
loss of safety due to lack of redundancy.

John Max Skaller                ph:61-2-96600850
mailto:skaller@zip.com.au       10/1 Toxteth Rd
http://www.zip.com.au/~skaller  Glebe 2037 NSW AUSTRALIA
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: ark@research.att.com (Andrew Koenig)
Date: 1997/11/07
Raw View
In article <34622a17.2517615429@news.zip.com.au> skaller@zip.com.au writes:

> A  language like SML doesn't need ANY type declarations.
> The type of everything is always known by the compiler.

> This completely eradicates the need for template functions.
> (Every function is _automatically_ generic)
> The cost: NO automatic conversions. And also,
> loss of safety due to lack of redundancy.

These statements don't quite tell the whole truth.

In the world of ordinary expressions, type declarations are
necessary in the presence of overloading and nowhere else.
Moreover, only built-in operators are overloaded.  But,
for example, SML requires a type declaration here:

 fun sum(x, y) = x + y  (* illegal, no type specified *)

because the compiler doesn't know whether you mean integer or real
addition.  SML97 solves this problem a different way, by assuming
integer addition.

However, SML also has a module system, which is intended to allow
large systems to be broken into parts that can be compiled (and
type-checked) separately.  Type declarations are absolutely essential
in the module system, because they are one of the main ways of expressing
dependencies between modules.
--
    --Andrew Koenig
      ark@research.att.com
      http://www.research.att.com/info/ark
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/11/04
Raw View
Christopher Eltschka wrote:
>
> Fergus Henderson wrote:
> >
> > Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
> [...]
>
> > >If already making a special case, I'd prefer to allow the syntax
>    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >typeof(A*B), as this is not only simpler and more intuitive, but
> > >wouldn't have *any* meaning without the extra rule.
> > >
> > >This could be formalized by saying that a typename used as operand
> > >in an expression used as argument of typeof should be equivalent
> > >to a subexpression with typeof(subexpression) equal to the type.

This isn't a complete rule; how is overload resolution done
for A*B ? Saying for some invented object of type A and B isn't
sufficient. Are these invented object temporaries or named
variables (lvalues) ?

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/11/05
Raw View
Valentin Bonnard wrote:
>
> Christopher Eltschka wrote:
> >
> > Fergus Henderson wrote:
> > >
> > > Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
> >
> > [...]
> >
> > > >If already making a special case, I'd prefer to allow the syntax
> >    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > >typeof(A*B), as this is not only simpler and more intuitive, but
> > > >wouldn't have *any* meaning without the extra rule.
> > > >
> > > >This could be formalized by saying that a typename used as operand
> > > >in an expression used as argument of typeof should be equivalent
> > > >to a subexpression with typeof(subexpression) equal to the type.
>
> This isn't a complete rule; how is overload resolution done
> for A*B ? Saying for some invented object of type A and B isn't
> sufficient. Are these invented object temporaries or named
> variables (lvalues) ?

Well, I'd vote for rvalues, as this is how such typenames are
usually treated f.ex. in typecasts. To get an lvalue, you then could
use (A&)*(B&).
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/11/01
Raw View
Fergus Henderson wrote:

> or a template
>
>         template <class T>
>         T expr_of_type() {
>                 throw "expr_of_type should only be used inside typeof()";
>         }

I don't think that an expression in typeof should be potentially
evaluated, so not defining expr_of_type() should be enough:

template <class T>
T expr_of_type(); // don't call; never defined

typeof (sin (expr_of_type<A> ())) x;

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: ark@research.att.com (Andrew Koenig)
Date: 1997/11/01
Raw View
In article <VA.0000003c.3c4a7fc4@jll_p133.INFOCAHB> jll@skynet.be writes:

> In article <EIK946.6vL@research.att.com>, Andrew Koenig wrote:
> > a more general solution

> Like what?

If I knew, I'd say.

I just have a hunch there's a much better solution out there,
and that we should spend some time looking for it.
--
    --Andrew Koenig
      ark@research.att.com
      http://www.research.att.com/info/ark
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/11/04
Raw View
Fergus Henderson wrote:
>
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

[...]

> >If already making a special case, I'd prefer to allow the syntax
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >typeof(A*B), as this is not only simpler and more intuitive, but
> >wouldn't have *any* meaning without the extra rule.
> >
> >This could be formalized by saying that a typename used as operand
> >in an expression used as argument of typeof should be equivalent
> >to a subexpression with typeof(subexpression) equal to the type.
>
> What if the same name is in scope as both a typename and as a
> variable?

I think in this case the program would be ill-formed anyway.
(Could you please give a valid example?)

BTW, I didn't say I want a special case (special cases are
usually bad). Just *if* there is one, it should not be to allow
the default constructor for types that don't have one (as proposed
by Brian Parker). And IMHO the typeof(A*B) syntax is quite
intuitive, and therefore the best candidate. But of course
having no special case is probably the better solution.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/10/30
Raw View
Brian Parker wrote:
>
> On 28 Oct 97 07:08:07 GMT, Christopher Eltschka
> <celtschk@physik.tu-muenchen.de> wrote:
> >...
> >what about:
> >
> >typeof( (*(A*)0) * (*(B*)0) )
> >
> >As typeof would not evaluate its argument, the "dereferencing" of
> >null pointers would not be a problem.
> >...
>
> Yes, that's a good work-around...still it's a little messy; it may be
> better to define typeof( )  to always accept typeof(A() * B())
> regardless of whether the default constructors are accessible.

If already making a special case, I'd prefer to allow the syntax
typeof(A*B), as this is not only simpler and more intuitive, but
wouldn't have *any* meaning without the extra rule.

This could be formalized by saying that a typename used as operand
in an expression used as argument of typeof should be equivalent
to a subexpression with typeof(subexpression) equal to the type.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/10/30
Raw View
ark@research.att.com (Andrew Koenig) writes:

>In article <62vmbf$79s@mulga.cs.mu.OZ.AU> fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>> >Because then the result of compose() cannot itself be used as
>> >an operand in another call to compose().
>
>> Why not?
>
>Because its argument type is then not a type, but a template,
>and I don't know how to overload a function (i.e. compose) to
>take either a type or a template.

Hang on -- compose itself is a function template, but the type of any
given call to compose() is a type, not a template.

For example, suppose compose() is defined as follows.

 template <class F, class G>
 class Compose {
  F f;
  G g;
 public:
  Compose(F ff, G gg) : f(ff), g(gg) {}
  template <class T>
  typeof(f(g(*(T*)0))) operator() (T x) {
   return f(g(x));
  }
 };

 template <class F, class G>
 Compose<F, G> compose(F f, G g) {
  return Compose<F, G>(f, g);
 }

Also suppose we have the following function declarations in scope.

 int f(int);
 int g(int);
 int h(int);

Then the expression

 compose(f, g)

has type

 Compose<int(*)(int), int(*)(int)>

and so

 compose(f, compose(g, h))

should work fine -- it would have type

 Compose<int(*)(int), Compose<int(*)(int), int(*)(int)> >

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: petteri.ollila@tietogroup.com (Petteri Ollila)
Date: 1997/10/30
Raw View
On 24 Oct 97 16:23:37 GMT, ark@research.att.com (Andrew Koenig) wrote:
[...]
>Whether you understood the previous paragraph or not, the main problem
>is that writing such a class requires the ability to look at g and
>figure out its argument type.  The reason is that the argument type of
>h must be the same as that of g, whatever it might be.
>
>The standard library solves this problem with the convention that if
>G is the type of g, and g is a function object that takes a single argument,
>then G::argument_type is the type of that argument.  This convention is
>a bit of a pain, but typeof wouldn't make it any easier.
>
>Because such usages are so common in the library, I am presently inclined
>against typeof, and would rather look for a more general solution.

Would signatureof(), in addition to typeof() help?

bool foo( int i ) ;
typeof(foo) foob( signatureof(foo) ) ;

__
Petteri Ollila
Tieto Group
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/10/30
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:

>Brian Parker wrote:
>>
>> On 28 Oct 97 07:08:07 GMT, Christopher Eltschka
>> <celtschk@physik.tu-muenchen.de> wrote:
>> >...
>> >typeof( (*(A*)0) * (*(B*)0) )
>> >
>> >As typeof would not evaluate its argument, the "dereferencing" of
>> >null pointers would not be a problem.
>> >...
>>
>> Yes, that's a good work-around...still it's a little messy; it may be
>> better to define typeof( )  to always accept typeof(A() * B())
>> regardless of whether the default constructors are accessible.
>
>If already making a special case, I'd prefer to allow the syntax
>typeof(A*B), as this is not only simpler and more intuitive, but
>wouldn't have *any* meaning without the extra rule.
>
>This could be formalized by saying that a typename used as operand
>in an expression used as argument of typeof should be equivalent
>to a subexpression with typeof(subexpression) equal to the type.

What if the same name is in scope as both a typename and as a
variable?

I think any such special case rule would be a horrible hack.

If `*(A *)0' is too messy (and I do have some sympathy for that
point of view), then use a macro

 #define expr_of_type(A) (*(A *)0)
 ...
 typeof(expr_of_type(A) * expr_of_type(B));

or a template

 template <class T>
 T expr_of_type() {
  throw "expr_of_type should only be used inside typeof()";
 }
 ...
 typeof(expr_of_type<A>() * expr_of_type<B>());

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Jean-Louis Leroy <jll@skynet.be>
Date: 1997/10/28
Raw View
In article <EIK946.6vL@research.att.com>, Andrew Koenig wrote:
> a more general solution

Like what?

Jean-Louis Leroy
http://ourworld.compuserve.com/homepages/jl_leroy
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Jean-Louis Leroy <jll@skynet.be>
Date: 1997/10/28
Raw View
In article <EIK946.6vL@research.att.com>, Andrew Koenig wrote:

> the main problem
> is that writing such a class requires the ability to look at g and
> figure out its argument type


I haven't read "ruminations" yet but I intend to. Thus I don't have
full understanding of the charade yet ;) Can't you use template
argument deduction on pointers to member functions?

template<class Result, class Functor, class Arg>
Arg arg_type(Result (Functor::*)(Arg))
   {
   }

This allows us to extract the type of the argument (at runtime):

template<class Functor>
void show_arg_type(Functor f)
   {
   cout << typeid(arg_type(&Functor::operator ())).name() << endl;
   }

It works with plain functions:

template<class Result, class Arg>
Arg arg_type(Result (*)(Arg))
   {
   return Arg();
   }

template<class Result, class Arg>
void show_arg_type(Result (*function)(Arg))
   {
   cout << typeid(arg_type(function)).name() << endl;
   }

struct F1
   {
   void operator ()(int);
   };

void f2(char) { }

int main()
   {
   show_arg_type(F1()); // print "int"
   show_arg_type(f2); // print "char"
   return 0;
   }

If we had typeof, we could use it in place of typeid and get hold of
the arguments at compile time. We'd have two (partial) specializations,
one for functors and one for functions. The body of the two arg_type
helpers wouldn't be needed because typeof wouldn't evaluate the
expression. We could omit them and avoid relying on the availability of
default ctors.

I think ;)

Jean-Louis Leroy
http://ourworld.compuserve.com/homepages/jl_leroy
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: ark@research.att.com (Andrew Koenig)
Date: 1997/10/29
Raw View
In article <62vmbf$79s@mulga.cs.mu.OZ.AU> fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:

> >Because then the result of compose() cannot itself be used as
> >an operand in another call to compose().

> Why not?

Because its argument type is then not a type, but a template,
and I don't know how to overload a function (i.e. compose) to
take either a type or a template.
--
    --Andrew Koenig
      ark@research.att.com
      http://www.research.att.com/info/ark
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: bparker@mailbox.uq.edu.au (Brian Parker)
Date: 1997/10/29
Raw View
On 28 Oct 97 07:08:07 GMT, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
>...
>what about:
>
>typeof( (*(A*)0) * (*(B*)0) )
>
>As typeof would not evaluate its argument, the "dereferencing" of
>null pointers would not be a problem.
>...

Yes, that's a good work-around...still it's a little messy; it may be
better to define typeof( )  to always accept typeof(A() * B())
regardless of whether the default constructors are accessible.

Thanks,
Brian Parker.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: bparker@mailbox.uq.edu.au (Brian Parker)
Date: 1997/10/26
Raw View
On 24 Oct 97 18:10:58 GMT, fjh@murlibobo.cs.mu.OZ.AU (Fergus
Henderson) wrote:
>...
>Well, I haven't tried this myself, so I am probably missing something --
>but why not make the h.operator()() function be a template member
>function?
>
> template <class F, class G>
> class Compose<F, G> {
>  F f;
>  G g;
> public:
>  Compose(F ff, G gg) : f(ff), g(gg) {}
>
>  template <class T>
>  typeof(f(g(x))) operator() (T x) {
>   return f(g(x));
>  }
> };
>
> template <class F, class G>
> Compose<F, G> compose(F f, G g) {
>  return Compose<F, G>(f, g);
> }

I think that if the template argument deduction rules for functions
were changed such that otherwise non-deducible template function
return types were deduced to be the type of the function's return
statement(s), then typeof wouldn't be necessary here i.e.-

  template <class R, class T>
  R operator() (T x) {
   return f(g(x));
  }
where R automatically defaults to be the type of f(g(x)) when called
(if all return statement types were not identical then deduction would
fail as usual).

Though I don't know whether such a rule would be practicable as it
involves analysing the function itself, not just its declaration-
exported templates in particular might be a problem.

,Brian Parker.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/10/26
Raw View
bparker@mailbox.uq.edu.au (Brian Parker) writes:

 >fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) wrote:
 >>...
 >>Well, I haven't tried this myself, so I am probably missing something --
 >>but why not make the h.operator()() function be a template member
 >>function?
 >>
 >> template <class F, class G>
 >> class Compose<F, G> {
 >>  F f;
 >>  G g;
 >> public:
 >>  Compose(F ff, G gg) : f(ff), g(gg) {}
 >>
 >>  template <class T>
 >>  typeof(f(g(x))) operator() (T x) {
 >>   return f(g(x));
 >>  }
 >> };
 >>
 >> template <class F, class G>
 >> Compose<F, G> compose(F f, G g) {
 >>  return Compose<F, G>(f, g);
 >> }
 >
 >I think that if the template argument deduction rules for functions
 >were changed such that otherwise non-deducible template function
 >return types were deduced to be the type of the function's return
 >statement(s), then typeof wouldn't be necessary here

Perhaps, but that change would be a bad idea, IMHO, for
reasons you state yourself:

 >Though I don't know whether such a rule would be practicable as it
 >involves analysing the function itself, not just its declaration-
 >exported templates in particular might be a problem.

I think `typeof' would be a cleaner solution to this particular
problem.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: ark@research.att.com (Andrew Koenig)
Date: 1997/10/26
Raw View
In article <62qmic$ba3@mulga.cs.mu.OZ.AU> fjh@murlibobo.cs.mu.OZ.AU
(Fergus Henderson) writes:

> Well, I haven't tried this myself, so I am probably missing something --
> but why not make the h.operator()() function be a template member
> function?

Because then the result of compose() cannot itself be used as
an operand in another call to compose().
--
    --Andrew Koenig
      ark@research.att.com
      http://www.research.att.com/info/ark
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/10/26
Raw View
ark@research.att.com (Andrew Koenig) writes:

>fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>> Well, I haven't tried this myself, so I am probably missing something --
>> but why not make the h.operator()() function be a template member
>> function?
>
>Because then the result of compose() cannot itself be used as
>an operand in another call to compose().

Why not?

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: bparker@mailbox.uq.edu.au (Brian Parker)
Date: 1997/10/27
Raw View
On 26 Oct 97 12:05:27 GMT, fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
wrote:
>...
> >I think that if the template argument deduction rules for functions
> >were changed such that otherwise non-deducible template function
> >return types were deduced to be the type of the function's return
> >statement(s), then typeof wouldn't be necessary here
>
>Perhaps, but that change would be a bad idea, IMHO, for
>reasons you state yourself:
>
> >Though I don't know whether such a rule would be practicable as it
> >involves analysing the function itself, not just its declaration-
> >exported templates in particular might be a problem.
>
>I think `typeof' would be a cleaner solution to this particular
>problem.
>..

Yes, I'd prefer having the full typeof solution myself. Automatically
deducing the return type is just a possible way to get some of the
benefits of typeof for the common case of its use in function return
with no new syntax.

There is the minor problem with typeof in a function return because
there is no particular expression that one could use there, and the
template arguments may not have default constructors so e.g.
typeof(A() * B()) may not be valid (probably typeof would need to be
defined to ignore the legality of the expression itself and only use
the type information, or allow e.g. typeof(A * B) which may cause its
own syntax problems).

For non-exported templates, I think that implementing the return type
solution would not pose too much of a problem, but the more I think
about separately compiled templates the more I don't like it either.

,Brian Parker
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/10/28
Raw View
Brian Parker wrote:

[...]

> There is the minor problem with typeof in a function return because
> there is no particular expression that one could use there, and the
> template arguments may not have default constructors so e.g.
> typeof(A() * B()) may not be valid (probably typeof would need to be

what about:

typeof( (*(A*)0) * (*(B*)0) )

As typeof would not evaluate its argument, the "dereferencing" of
null pointers would not be a problem.

[...]
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/10/28
Raw View
Andrew Koenig wrote:
>
> In article <344E556A.12AF@shellus.com> Ian Haggard <ian@shellus.com> writes:
>
> > If typeof had been available, then the standards committee would not
> > have had to add the iterator_traits class to the standard.  Moreover, we
> > could be avoiding, for the most part, the proliferation of traits
> > classes that seem to be littered throughout the standard library.  Not
> > that I object to traits classes when they are truly necessary, but I
> > think that in many cases they could be eliminated if C++ had typeof.
>
> Well, yes and no.  I used to think that typeof would solve many more
> problems than I now think it does.
>
> As a simple example of a problem that typeof doesn't solve,
> think about writing a function object class, along the lines
> of the one in Chapter 21 of `Ruminations on C++,' whose objects
> represent the compositions of other function objects.
>
> That is, if f and g are function objects (or, ideally, functions
> as well), I would like to be able to create a new object
> compose(f, g), with the property that after I have said
>
>         h = compose(f, g)
>
> then h(x) is equivalent to f(g(x)).
>
> Whether you understood the previous paragraph or not, the main problem
> is that writing such a class requires the ability to look at g and
> figure out its argument type.  The reason is that the argument type of
> h must be the same as that of g, whatever it might be.
>
> The standard library solves this problem with the convention that if
> G is the type of g, and g is a function object that takes a single argument,
> then G::argument_type is the type of that argument.  This convention is
> a bit of a pain, but typeof wouldn't make it any easier.
>
> Because such usages are so common in the library, I am presently inclined
> against typeof, and would rather look for a more general solution.

With typeof, there _would_ be a solution:

// argument types:

// member functions
template<typename arg, typename ret, typename cls>
 arg* argument_type(ret (cls::*)(arg))
{
  return 0;
}

// normal functions
template<typename arg, typename ret>
 arg* argument_type(ret (*)(arg))
{
  return 0;
}

// function objects
template<typename fun_obj>
 typeof(argument_type(&fun_obj::operator())* argument_type(fun_obj*)
{
  return 0;
}

// return types:

// member functions
template<typename arg, typename ret, typename cls>
 ret* return_type(ret (cls::*)(arg))
{
  return 0;
}

// normal functions
template<typename arg, typename ret>
 ret* return_type(ret (*)(arg))
{
  return 0;
}

// function objects
template<typename fun_obj>
 typeof(return_type(&fun_obj::operator())* return_type(fun_obj*)
{
  return 0;
}

template<typename fun1, typename fun2>
 class composed_function
{
public:
  typedef typeof(return_type((fun1*)0)) result_type;
  typedef typeof(argument_type((fun2*)0)) argument_type;

  composed_function(fun1, fun2);
  argument_type operator()(result_type);
...
};

template<typename fun1, typename fun2>
 composed_function<fun1, fun2> compose(const fun1& f, const fun2& g)
{
  return composed_function<fun1, fun2>(f,g);
}
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/10/24
Raw View
ark@research.att.com (Andrew Koenig) writes:

>As a simple example of a problem that typeof doesn't solve,
>think about writing a function object class, along the lines
>of the one in Chapter 21 of `Ruminations on C++,' whose objects
>represent the compositions of other function objects.
>
>That is, if f and g are function objects (or, ideally, functions
>as well), I would like to be able to create a new object
>compose(f, g), with the property that after I have said
>
> h = compose(f, g)
>
>then h(x) is equivalent to f(g(x)).
>
>Whether you understood the previous paragraph or not, the main problem
>is that writing such a class requires the ability to look at g and
>figure out its argument type.  The reason is that the argument type of
>h must be the same as that of g, whatever it might be.

Well, I haven't tried this myself, so I am probably missing something --
but why not make the h.operator()() function be a template member
function?

 template <class F, class G>
 class Compose<F, G> {
  F f;
  G g;
 public:
  Compose(F ff, G gg) : f(ff), g(gg) {}

  template <class T>
  typeof(f(g(x))) operator() (T x) {
   return f(g(x));
  }
 };

 template <class F, class G>
 Compose<F, G> compose(F f, G g) {
  return Compose<F, G>(f, g);
 }

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: ark@research.att.com (Andrew Koenig)
Date: 1997/10/24
Raw View
In article <344E556A.12AF@shellus.com> Ian Haggard <ian@shellus.com> writes:

> If typeof had been available, then the standards committee would not
> have had to add the iterator_traits class to the standard.  Moreover, we
> could be avoiding, for the most part, the proliferation of traits
> classes that seem to be littered throughout the standard library.  Not
> that I object to traits classes when they are truly necessary, but I
> think that in many cases they could be eliminated if C++ had typeof.

Well, yes and no.  I used to think that typeof would solve many more
problems than I now think it does.

As a simple example of a problem that typeof doesn't solve,
think about writing a function object class, along the lines
of the one in Chapter 21 of `Ruminations on C++,' whose objects
represent the compositions of other function objects.

That is, if f and g are function objects (or, ideally, functions
as well), I would like to be able to create a new object
compose(f, g), with the property that after I have said

 h = compose(f, g)

then h(x) is equivalent to f(g(x)).

Whether you understood the previous paragraph or not, the main problem
is that writing such a class requires the ability to look at g and
figure out its argument type.  The reason is that the argument type of
h must be the same as that of g, whatever it might be.

The standard library solves this problem with the convention that if
G is the type of g, and g is a function object that takes a single argument,
then G::argument_type is the type of that argument.  This convention is
a bit of a pain, but typeof wouldn't make it any easier.

Because such usages are so common in the library, I am presently inclined
against typeof, and would rather look for a more general solution.
--
    --Andrew Koenig
      ark@research.att.com
      http://www.research.att.com/info/ark
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]