Topic: Suggestion: "typeof" keyword
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/09/01 Raw View
blargg wrote:
> And a register can certainly have its address taken (in C++, which is in
> the title of this newsgroup!).
Yes, but the standard says that the hint provided by designating a
variable 'register', is likely to be ignored if the address of that
variable is taken. In other words, if you take it's address, it probably
won't be assigned to a machine register.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/28 Raw View
Max TenEyck Woodbury <mtew@cds.duke.edu> writes:
>blargg wrote:
>>
>> What the hell is "typeof a type" for? Typeof a type is the type.
>> It's useless.
>
>While you don't need 'typeof <<type>>', it would make a bit more sense
>in some cases to specify the types needed for a function signature
>directly rather than having to supply an instance. Something like:
>
> typeof func( class xyz)
>
>which provides exactly the excuse needed to bring it closer to the
>sizeof syntax. 'typeof (<<expr>>)' or typeof <<function signature>>.
I don't understand what you're getting at here.
Is `typeof func(class xyz)' supposed to be a type, or a declaration?
What semantics is it supposed to have?
How does `typeof func(class xyz)' differ from `func(class xyz)'?
If `func(class xyz)' is a function signature, then `func' must be
a type (the return type), not a function name, so your example
seems misleading. And `typeof (int(float))' would be the same
as `int(float)' -- both of them would name the type "function
taking float and returning 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/29 Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>niklasb@my-deja.com wrote:
>>
>> You've convinced me. The reference should be stripped,
>> but the CV qualifier should be retained. Just to give
>> something concrete to talk about, let me try once again
>> to suggest a set of rules:
...
>> 3 Within the context of a typeof expression, a temporary
>> object of any type T can be instantiated using
>>
>> - initialization notation, T(), whether or not
>> T has a default constructor, or
>>
>> - cast notation, (T)expr, whether or not a
>> conversion from typeof(expr) to T exists.
Why allow both of these? Surely allowing one of them would be sufficient.
I still don't see why any of these is better than `*(T*)NULL'.
>I'd restrict this to special expressions; a good candidate
>would be the same as currently the null pointer constant,
>since this already is very special.
>
>Thus in typeof expressions
>
> (T)0 would be legal and an rvalue
> (T&)0 would be legal and an lvalue
You could use `(T)*(T*)NULL' for a null pointer, although admittedly that
is not particularly pleasant syntax.
I think the need to distinguish between rvalues and lvalues would be rare.
If you don't like that syntax, you can easily define template functions
template <class T> T rvalue();
template <class T> T& lvalue();
and then use `rvalue<T>()' and `lvaue<T>()'.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/30 Raw View
postmast.root.admi.gov@iname.com (blargg) writes:
> I simply do not like these added syntactic elements, becuase I don't think
> they're necessary. I believe that templates provide all we need to make
> temporaries to get their types in expressions.
> template<typename R>
> struct func_ret_type_<T (*f)()> {
> typedef R type;
> };
...
> template<typename F>
> typename func_ret_type_<F>::type func_ret_type( F );
This is illegal, of course. You have specified func_ret_type_ as taking
a non-type pointer-to-function parameter. When you supply an argument,
it must be the address of a function with external linkage. Instead,
you are supplying a type. You *can* do
template < typename R > struct func_ret_type_ < R (*)() > { ... };
The problem with this is approach is that you restrict use to actual
function pointers, whereas the typeof approach allows those, plus
functors, plus objects that are convertible to functors, and so on.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/30 Raw View
Fergus Henderson wrote:
>
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
>>niklasb@my-deja.com wrote:
>>>
>>> You've convinced me. The reference should be stripped,
>>> but the CV qualifier should be retained. Just to give
>>> something concrete to talk about, let me try once again
>>> to suggest a set of rules:
> ...
>>> 3 Within the context of a typeof expression, a temporary
>>> object of any type T can be instantiated using
>>>
>>> - initialization notation, T(), whether or not
>>> T has a default constructor, or
>>>
>>> - cast notation, (T)expr, whether or not a
>>> conversion from typeof(expr) to T exists.
>
> Why allow both of these? Surely allowing one of them would
> be sufficient.
>
> I still don't see why any of these is better than `*(T*)NULL'.
'T' might be a type that does not allow its address to be taken,
like a bit field or a register.
Which brings up another question. Should type modifiers like
'register', 'static' and 'auto' be dropped when you use 'typeof'?
I think the answer should be yes.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/31 Raw View
blargg wrote:
>
>
> I simply do not like these added syntactic elements, becuase I don't think
> they're necessary. I believe that templates provide all we need to make
> temporaries to get their types in expressions.
But you should be able to get at the return type without creating an
unneeded temporary.
[snip incomprehensible example...]
> The reason I don't like these extra syntactic elements is that there are
> so many one could think to add. If the language allows it in a
> relatively-concise way, then do it that way.
>
>> which provides exactly the excuse needed to bring it closer to the
>> sizeof syntax. 'typeof (<<expr>>)' or typeof <<function signature>>.
>
> Uck. And I suppose you also want to add little syntactic elements to allow
> finding out the type of argument n?
1. OK, so my phrasing is atrocious.
2. If you have the signature, you already have the nth argument type. What
you may want to find out is the return type without having to specify
a whole bunch of dummy argument instances.
> Please, let's look for solutions that involve minimal new elements that
> work in many ways with *current* elements. C++ doesn't need more feature
> creep.
Let's also make the result understandable. If you really want to get
minimal, you could eliminate all operators except ^=, >>= and <<= but
the result would be almost impossible to understand.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/31 Raw View
In article <37C3DA57.25C88799@physik.tu-muenchen.de>,
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> "Siemel B. Naran" wrote:
> >
> > On 19 Aug 1999 16:39:34 GMT, Christopher Eltschka
> > >"Siemel B. Naran" wrote:
> >
> > >> In one of my posts I used this
> > >> typeof(A*B+C) MultiplyAdd(...) { ... }
> >
> > >That's problematic:
> > >
> > >class X {};
> > >class Y { Y operator*(); };
> > >X operator*(X, Y);
> > >Y operator*(X*, Y);
> > >
> > >typeof(X**Y) a
> >
> > The notation "X*" to mean pointer to an 'X' is wrong.
>
> According to the current rules of writing types, writing
> "X*" to mean "pointer to X" is right.
Which simply demonstrates that the operand of typeof
should be an expression, not a type.
If A, B, and C are types, then typeof(A*B+C) would be
illegal because A*B+C is not an expression. What you're
looking for, I think, is
typeof( A()*B()+C() )
or if you prefer cast notation:
typeof( (A)0 * (B)0 + (C)0 )
Either could be read, "the type of (the result of) an
expression that: adds two objects of types A and B,
and then adds their sum with an object of type C."
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/31 Raw View
In article <t7u2phxilb.fsf@calumny.jyacc.com>, Hyman Rosen
<hymie@prolifics.com> wrote:
> postmast.root.admi.gov@iname.com (blargg) writes:
> > I simply do not like these added syntactic elements, becuase I don't think
> > they're necessary. I believe that templates provide all we need to make
> > temporaries to get their types in expressions.
> > template<typename R>
> > struct func_ret_type_<T (*f)()> {
^
typo - I meant R
> > typedef R type;
> > };
> ...
> > template<typename F>
> > typename func_ret_type_<F>::type func_ret_type( F );
>
> This is illegal, of course. You have specified func_ret_type_ as taking
> a non-type pointer-to-function parameter.
Duh. Mistake number two :-)
> When you supply an argument,
> it must be the address of a function with external linkage.
Yeah, that would also bite (if it worked, which it doesn't).
> Instead,
> you are supplying a type. You *can* do
>
> template < typename R > struct func_ret_type_ < R (*)() > { ... };
>
> The problem with this is approach is that you restrict use to actual
> function pointers, whereas the typeof approach allows those, plus
> functors, plus objects that are convertible to functors, and so on.
Yes, but I'm not convinced these can't also be handled with some sort of
template function.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/31 Raw View
In article <37CAE6FE.32E4DFEA@cds.duke.edu>, Max TenEyck Woodbury
<mtew@cds.duke.edu> wrote:
> Fergus Henderson wrote:
> >
> > Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
[snip]
> > I still don't see why any of these is better than `*(T*)NULL'.
>
> 'T' might be a type that does not allow its address to be taken,
> like a bit field or a register.
Isn't a bit field converted to an int before being used anyway?
And a register can certainly have its address taken (in C++, which is in
the title of this newsgroup!).
> Which brings up another question. Should type modifiers like
> 'register', 'static' and 'auto' be dropped when you use 'typeof'?
>
> I think the answer should be yes.
Uhhh, those aren't part of an object's type to begin with.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Greg Brewer" <nospam.greg@brewer.net>
Date: 1999/08/30 Raw View
> That's a new one - recovering destroyed information. You should
> immediately start working on a compression algorithm that does this.
> You'll make millions. Imagine, compress anything to 0 bytes! Ahem.
I already have an algorithm that will compress anything to 1 byte. I'm
looking for help with the decompression routine. Anyone.
Greg Brewer
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/28 Raw View
In article <wkwvuig1a1.fsf@newsguy.com>, Kevin Kostrzewa
<tkkost@newsguy.com> wrote:
> postmast.root.admi.gov@iname.com (blargg) writes:
> > > class Foo;
> > > typeof<Foo>()::type t;
> >
> > Hello? What is this for?
>
> Just trying to cover all of the bases of the syntax for typeof that
> people had been discussing in this thread recently.
[snip]
Even the pointless ones... heh
> > > Foo f;
> > > typeof(f)::type t;
> > >
> > > Also, if typeof is written in terms of the language,
> >
> > Which can't be done, so this is not an issue. typeof cannot be implemented
> > with the current language.
>
> That's right. I was taking Siemel's idea of allowing :: to be used on
> an expression and running with the concept. Sorry again if that
> wasn't obvious.
This is funny. Everyone keeps attributing the ideas to different people
:-) I'd like to make proper attributions.
I had suggested allowing a type to be accessed of a pointer/ref using
normal member access syntax
ref.type x = y;
ptr->type x = y;
This was partly based on a freak incident that I caught where my compiler
was allowing a temporary to be created from a type accessed off a
*pointer*. How's that for a compiler bug being the source of an idea? :-)
Then, Christopher Eltschka suggested that the scope resolution operator
(::) be used instead, since it never evaluates its LHS (the LHS is never
an expression anyway). The reasoning was that it would be more intuitive
than member access, since (now) the LHS is always evaluated. I guess I
consider this a little better, though it makes access off a pointer
inconvenient:
(*ptr)::type // instead of ptr->type
However, it is perhaps clearer that type isn't a data/function member, as
it may seem if accessed using normal member syntax. Consider this:
f( p->x( y ) );
Is x a type or function (or member)? Could be any. Not that this is
necessarily a problem, as this sort of encapsulation could be useful at
times.
> > [snip declare mess :-) ]
>
> Yeah, it was pretty messy. Just thinking out loud.
A good thing. Put all the ideas on the table, then sort them out. Save the
crazy ones for a rainy day :-)
Please don't let my criticisim of ideas (or anyone else's) discourage you
from posting them. I see myself (and others) separate from their ideas. As
long as one keeps detachment, one can be productive in improving the ideas
on the table. Bad idea? Put it aside.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/28 Raw View
In article <37C45EDB.55BF9E6D@cds.duke.edu>, Max TenEyck Woodbury
<mtew@cds.duke.edu> wrote:
> blargg wrote:
> >
> > <tkkost@newsguy.com> wrote:
> >
> > > ...
> > > If, as Siemel suggested,
> > > :: could be applied to the return type of a function, typeof could be
> > > written in terms of the language, but it would have to have a slightly
> > > different syntax if you wanted the typeof an expression
> >
> > OK, type of an expression make sense.
> >
> > > vs. the typeof a type:
> >
> > Uhhh, I don't follow. Common-sense on. What the hell is "typeof a type"
> > for? Typeof a type is the type. It's useless. I'll repeat what I posted a
> > few days ago:
> >
> > typeof (typeof (typeof (typeof (typeof (typeof (typeof (int))))))))
>
> While you don't need 'typeof <<type>>', it would make a bit more sense
> in some cases to specify the types needed for a function signature
> directly rather than having to supply an instance. Something like:
>
> typeof func( class xyz)
I simply do not like these added syntactic elements, becuase I don't think
they're necessary. I believe that templates provide all we need to make
temporaries to get their types in expressions.
template<typename F>
struct func_ret_type_;
template<typename R>
struct func_ret_type_<T (*f)()> {
typedef R type;
};
template<typename R,typename A1>
struct func_ret_type_<T (*f)( A1 )> {
typedef R type;
};
// etc.
template<typename F>
typename func_ret_type_<F>::type func_ret_type( F );
void f( Func f ) { // we don't know the exact typedef
typeof (func_ret_type( f )) ret = f();
}
The reason I don't like these extra syntactic elements is that there are
so many one could think to add. If the language allows it in a
relatively-concise way, then do it that way.
> which provides exactly the excuse needed to bring it closer to the
> sizeof syntax. 'typeof (<<expr>>)' or typeof <<function signature>>.
Uck. And I suppose you also want to add little syntactic elements to allow
finding out the type of argument n?
Please, let's look for solutions that involve minimal new elements that
work in many ways with *current* elements. C++ doesn't need more feature
creep.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/08/24 Raw View
Lisa Lippincott <lisa_lippincott@advisories.com> writes:
>> Here's a potential trouble spot with typeof: it allows a program to refer
>> to unnamed classes and enums, which may cause havoc with linkage.
>> Consider:
>>
>> enum {a};
>> enum {b};
>> void f( typeof(a) );
>> void f( typeof(b) );
>>
>> What are the linkage names of the functions f?
Hyman Rosen <hymie@prolifics.com> wrote:
> Is the following illegal? Gcc compiles it without error or warning.
>
> #include <iostream>
> enum { a }; enum { b };
> template <typename T> void f(T v) { cout << v << endl; }
> int main() { f(a); f(b); }
Other than the lack of "std::" before "cout" and "endl", I don't see
anything wrong with the code above.
On the other hand, your example doesn't address the point of Lisa's example.
Your example calls the std::basic_ostream<> inserter for one of the integral
types. Since there's no exact match for the anonymous enum type, overload
matching performs standard conversions, which include integral promition of
an rvalue of enumerated type to int, unsigned int, long, or unsigned long.
-- Darin
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/24 Raw View
On 24 Aug 1999 18:10:33 GMT, Hyman Rosen <hymie@prolifics.com> wrote:
>Lisa Lippincott <lisa_lippincott@advisories.com> writes:
>> Here's a potential trouble spot with typeof: it allows a program to refer
>> to unnamed classes and enums, which may cause havoc with linkage.
>#include <iostream>
>enum { a }; enum { b };
>template <typename T> void f(T v) { cout << v << endl; }
>int main() { f(a); f(b); }
The EDG compiler says that the calls f(a) and f(b) are errors. The
error message: "a template argument may not reference an unnamed
type".
The egcs compiler compiles it fine. It uses the anonymous enum in
its error messages too. I made this program:
#include <iostream>
enum { a }; enum { b };
template <typename T> void f(T v) { cout += v; }
int main() { f(a); f(b); }
Both error messages start as follows:
unnamed.cc: In function `void f<{anonymous enum}>(enum {anonymous})':
But it seems to me that they should be
unnamed.cc: In function `void f<{unnamed.cc :: anonymous_enum 1}>
unnamed.cc: In function `void f<{unnamed.cc :: anonymous_enum 2}>
So who is right according to the standard?
14.3.1 Template type arguments
1 ...
2 A local type with no linkage, an unnamed type, or a type
compounded from any of these types shall not be used as a
template-argument for a template type-parameter.
3 ...
Seems like EDG wins the day!.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Kevin Kostrzewa <tkkost@newsguy.com>
Date: 1999/08/24 Raw View
sbnaran@uiuc.edu (Siemel B. Naran) writes:
> I think that allowing "::" to be applied to the return types of
> functions but not introducing the 'typeof' keyword would be a
> better idea than introducing the 'typeof' keyword but leaving
> the "::" rules alone. Then we could implement struct typeof in
> terms of the existing core language. This saves us the ordeal
> of figuring out the semantics of 'typeof'.
I totally agree, but I'd like :: to be able to be applied to any
expression, not just a function return type. If, as Siemel suggested,
:: could be applied to the return type of a function, typeof could be
written in terms of the language, but it would have to have a slightly
different syntax if you wanted the typeof an expression vs. the typeof
a type:
template<class T> struct Typeof_tp { typedef T type; };
template<class T> Typeof_tp<T> typeof(T) { return Typeof_tp<T>(); }
template<class T> Typeof_tp<T> typeof() { return Typeof_tp<T>(); }
class Foo;
typeof<Foo>()::type t;
Foo f;
typeof(f)::type t;
Also, if typeof is written in terms of the language, can we be
guaranteed that the expression passed down to the typeof() function
that accepts one parameter is not evaluated (like we are guaranteed
for sizeof() when it is passed an expression?) That might hinder
typeof(*(int *)0 + *(double *)0)::type t;
Finally, I think that the people who want declare, as well as typeof
can be appeased as well, as something like declare could be written
using the language:
// warning - this code will not compile! plus, it's pretty damn
// ugly.
template<class T>
class Declare_tp
{
public:
struct initialized_type
{
initialized_type() :
m_t(*Declare_tp<T>::s_ptcur)
{}
operator T &() { return m_t; }
operator const T &() const { return m_t; }
T *operator&() { return &m_t; }
const T *operator&() const { return &m_t; }
T &operator=(const T &other)
{
m_t = other;
return *this;
}
private:
T m_t;
};
static const T *s_ptcur;
Declare_tp(const T &tcur)
{
s_ptcur = &tcur;
}
typedef T type;
};
template<class T>
const T *Declare_tp<T>::s_ptcur;
// usage:
int x = 1;
double y = 2.5;
declare(x+2y)::initialized_type t;
declare(x+2y)::type t2;
// t should be 6.0 and convertable to double
// t2 should be of type double, uninitialized
--
kevin kostrzewa
work: kkostrzewa@csisolutions.com
home: tkkost@newsguy.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/25 Raw View
In article <wk4shp3qij.fsf@newsguy.com>, Kevin Kostrzewa
<tkkost@newsguy.com> wrote:
> sbnaran@uiuc.edu (Siemel B. Naran) writes:
> > I think that allowing "::" to be applied to the return types of
> > functions but not introducing the 'typeof' keyword would be a
> > better idea than introducing the 'typeof' keyword but leaving
> > the "::" rules alone. Then we could implement struct typeof in
> > terms of the existing core language. This saves us the ordeal
> > of figuring out the semantics of 'typeof'.
>
> I totally agree, but I'd like :: to be able to be applied to any
> expression, not just a function return type.
That was just one case of it. It was meant to be more general as you
describe. For example, it would allow convenient access of types off an
object:
for ( list::iterator iter( list.begin() ); iter != list.end(); ++iter ) {
// ...
}
It would also allow member function pointers to be obtained without
mentioning the class name:
struct Foo {
void f();
};
Foo* obj;
callback cb( obj, &(*obj)::f );
> If, as Siemel suggested,
> :: could be applied to the return type of a function, typeof could be
> written in terms of the language, but it would have to have a slightly
> different syntax if you wanted the typeof an expression
OK, type of an expression make sense.
> vs. the typeof a type:
Uhhh, I don't follow. Common-sense on. What the hell is "typeof a type"
for? Typeof a type is the type. It's useless. I'll repeat what I posted a
few days ago:
typeof (typeof (typeof (typeof (typeof (typeof (typeof (int))))))))
> template<class T> struct Typeof_tp { typedef T type; };
> template<class T> Typeof_tp<T> typeof(T) { return Typeof_tp<T>(); }
> template<class T> Typeof_tp<T> typeof() { return Typeof_tp<T>(); }
>
> class Foo;
> typeof<Foo>()::type t;
Hello? What is this for?
> Foo f;
> typeof(f)::type t;
>
> Also, if typeof is written in terms of the language,
Which can't be done, so this is not an issue. typeof cannot be implemented
with the current language.
> can we be
> guaranteed that the expression passed down to the typeof() function
> that accepts one parameter is not evaluated (like we are guaranteed
> for sizeof() when it is passed an expression?)
Well, if we're adding new features to the language, then perhaps the
feature typeof () could be implemented on could be such that it allows
typeof not to evaluate its expression.
That would be part of the semantics - the LHS of :: could be an expression
(as opposed to currently where it must be a type/namespace). The
expression would never be evaluated. In effect,
(expr)::identifier
would be equivalent to (using the typeof () proposal)
typeof (expr)::identifier
I like using the scope resolution operator better than typeof, because it
is more concise in accessing a typename off an object.
> That might hinder
>
> typeof(*(int *)0 + *(double *)0)::type t;
It also is a natural extension of the current syntax. In fact, I'm sure
many times people new to C++ have asked why this isn't already allowed. It
doesn't add yet another keyword.
[snip declare mess :-) ]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/08/25 Raw View
Me:
> On the other hand, your example doesn't address the point of Lisa's example.
Oops. I was wrong. Please excuse my earlier incorrect message.
-- Darin
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Salters <salters@lucent.com>
Date: 1999/08/25 Raw View
Siemel B. Naran wrote:
> On 23 Aug 99 20:32:16 GMT, blargg <postmast.root.admi.gov@iname.com> wrote:
> >In article <7pk70i$6as$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
> > template<class II>
> > II find(II begin, II end, const typeof(*II())& val );
> >> This allows for better parameter validation, and
> >> better diagnostics, because the compiler has more
> >> information about the parameter types.
> >That's interesting, but considering the things it wouldn't check, I don't
> >like this inconsistency. For example, find probably needs operator ++
> >defined, but that wouldn't be expressed in the interface.
> How about this
> template<class II>
> II find(II begin, II end, const typeof(*((++II())++))& val );
> This says that II must have an accessible
> default constructor
> pre-increment
> post-increment
> operator*
Do you really mean accessible? In general, should we restrict typeof()
to public parts? Or (makes more sense) should we do access control?
Or should we ignore it all together?
E.g., given
class Base {
private:
virtual A f();
public:
A do_f() {check_invariant();return f();}
}
class Derived {
typeof(Base::f()) f();
}
Normally, we can't call Base::f, but we must use the same return type.
typeof() provides us with (some) stability. Should this work?
(Never mind the design of f() )
Michiel Salters
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/25 Raw View
stanley@West.Sun.COM (Stanley Friesen [Contractor]) writes:
> In article <slrn7rph2r.e43.sbnaran@localhost.localdomain>,
> >The next question is what is more intuitive to use: that typeof throws
> >away top level const and value/reference distinction, or retains it?
> >
> Answer: keeps const/volatile, throws away value/reference.
I'm the one who posted the version that discarded top-level cv-qualifiers.
I've changed my mind. I agree that it is better to keep them because they
can be easily discarded if that's needed, while they can't be recovered if
they are always discarded.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/25 Raw View
"Siemel B. Naran" wrote:
>
> On 19 Aug 1999 16:39:34 GMT, Christopher Eltschka
> >"Siemel B. Naran" wrote:
>
> >> In one of my posts I used this
> >> typeof(A*B+C) MultiplyAdd(...) { ... }
>
> >That's problematic:
> >
> >class X {};
> >class Y { Y operator*(); };
> >X operator*(X, Y);
> >Y operator*(X*, Y);
> >
> >typeof(X**Y) a
>
> The notation "X*" to mean pointer to an 'X' is wrong.
According to the current rules of writing types, writing
"X*" to mean "pointer to X" is right.
> One should say
> "&X" to get a pointer to an 'X'.
This may not work if X has overloaded operator& to return
something different than X* (sic!)
> To summarize, "&X" means operator&
> applied to an X object -- in short, X::operator&. An "*Y" means
> operator* applied to a Y object -- in short, Y::operator*. So the
> meaning is unamgiguous: typeof(X**Y) is simply X.
You added a new rule on the fly to make it unambiguous.
The new rule is "you may not use any type that is not
given by a single name". Now if you should need such a type,
you must either name if (with an earlier typedef), or find an
expression which resolves to that type (your &X). It's a rule
that doesn't fit nicely into C++, where you can use the full
type notation everywhere you need a type.
A better way would be to make a special syntax for
"arbitrary object of type X", like [X]. Then the
example above would either read
typeof([X]**[Y])
where both * are operators, or
typeof([X*]*[Y])
where the first * is part of the type X*.
However, if you replace the syntax [X] by obj<X>(), you can
do it even without an additional extension, by just declaring
template<class T> T obj();
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/25 Raw View
niklasb@my-deja.com wrote:
>
> In article <37BD2185.C0047293@physik.tu-muenchen.de>,
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> >
> > [ snip ]
> >
> > I think top level const should be preserved (but I agree that
> > reference should be removed).
> >
> > [ snip ]
> >
> > And my expectation would be that the following should
> > always work:
> >
> > any_type foo;
> > typeof(foo)* bar = &foo;
> >
> > And now assume any_type is int const.
>
> You've convinced me. The reference should be stripped,
> but the CV qualifier should be retained. Just to give
> something concrete to talk about, let me try once again
> to suggest a set of rules:
>
> 1 The typeof operator yields the type of its operand.
> The operand is an expression, which is not evaluated.
> The result is the CV-qualified type of the expression
> (the static type, not the dynamic type of the object
> returned by the expression).
>
> <Example>
> void func();
> typeof(func)* fp = func;
> </Example>
>
> 2 The typeof operator never yields a reference type.
> When applied to a reference, the result is the
> referenced type.
>
> <Example>
> vector<int> v(1);
> typeof(v[0]) x = v[0]; // int x = v[0];
> typeof(v[0])& y = v[0]; // int& y = v[0];
> </Example>
>
> 3 Within the context of a typeof expression, a temporary
> object of any type T can be instantiated using
>
> - initialization notation, T(), whether or not
> T has a default constructor, or
>
> - cast notation, (T)expr, whether or not a
> conversion from typeof(expr) to T exists.
I'd restrict this to special expressions; a good candidate
would be the same as currently the null pointer constant,
since this already is very special.
Thus in typeof expressions
(T)0 would be legal and an rvalue
(T&)0 would be legal and an lvalue
(T)1 would be illegal, unless casting from int to T is allowed
IMHO having the cast notation suffices; the notation T() would
therefore not have to be legalized (it's more limited anyway,
since it can only produce rvalues).
So I'd replace your 3 with
3 Within the context of a typeof expression, an anonymous
object of type T can be denoted by casting a constant
integral expression of integer type evaluating to 0 to
either T or T& with a C-style cast. Here (T&)0 results
in an lvalue, while (T)0 results in an rvalue.
Note that I used the definition of the null pointer constant
instead of just saying "a null pointer constant casted to T",
so if the definition of a null pointer constant is ever changed
(f.ex. to make ((void*)0) a null pointer constant as well), this
rule is not affected (since the 0 in question is not a null
pointer constant, but only shares the current syntax).
>
> (Because the expression is not evaluated, it does
> not matter whether the temporary object can be
> initialized correctly.)
This should probably be a note, instead of normative text.
>
> 4 In a variable declaration, the typeof operand can
^^^^^^^^^^^ definition
> be "...", representing the expression used to
> initialize the variable.
>
> <Example>
> typeof(...) i = v.begin();
> typeof(...) j( v.end() );
> </Example>
This should probably be restricted to the "=" form, since
otherwise you'd get problems with expressions like
typeof(...) k(v.begin(), v.end());
Since the type of the old and new object is the same, the
definitions
T a = b;
and
T a(b);
are equivalent here anyway, so allowing the second form with
typeof(...) would only be syntactic sugar, but probably
complicate the wording much in order to prevent definitions
like k above.
One could also extend typeof(...) to use type deduction
rules similar to those used in templates.
The point would be that typeof(...) would not be seen in
isolation, but as part of the complete type. A possible
rule could be:
A complete type expression containing typeof(...) denotes
the type which results by replacing each instance of
typeof(...) by the type which it would result in on
template deduction on a template function using independant
type template parameters for all instances of typeof(...).
Examples:
int const a;
typeof(...) b = a;
// type deduction through template<class T> void __foo(T)
// __foo(a) deducts T to int
// therefore this resolves to
// int b = a;
typeof(...)& c = a;
// type deduction through template<class T> void __foo(T&)
// __foo(a) deducts T to int const
// therefore this resolves to
// int const& c = a;
typeof(...)* d = &a;
// type deduction through template<class T> void __foo(T*)
// __foo(&a) deducts T to int const
// therefore this resolves to
// int const* d = &a;
pair<typeof(...), typeof(...)> e = make_pair(c, d);
// type deduction through
// template<class T1, class T2> void __foo(pair<T1, T2>);
// __foo(make_pair(c,d)) deducts T1 to int and T2 to int*
// (since the return type of make_pair(c, d) is pair<int, int*>)
// therefore this resolves to
// pair<int, int*> e = make_pair(a, b);
Of course, this would be more complex than the simple
"rhs side type" rule, but also more flexible. Especially,
it would resolve the "CV problem" at least for the
typeof(...) case (see definitions of b, c and d above).
[...]
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Kevin Kostrzewa <tkkost@newsguy.com>
Date: 1999/08/26 Raw View
postmast.root.admi.gov@iname.com (blargg) writes:
> > class Foo;
> > typeof<Foo>()::type t;
>
> Hello? What is this for?
Just trying to cover all of the bases of the syntax for typeof that
people had been discussing in this thread recently. I understand your
point about this being useless, but all I wanted to discuss was
ramifications of allowing :: to be used on an expression with respect
to the proposed typeof and the proposed declare. Sorry if that wasn't
obvious.
>
> > Foo f;
> > typeof(f)::type t;
> >
> > Also, if typeof is written in terms of the language,
>
> Which can't be done, so this is not an issue. typeof cannot be implemented
> with the current language.
That's right. I was taking Siemel's idea of allowing :: to be used on
an expression and running with the concept. Sorry again if that
wasn't obvious.
> [snip declare mess :-) ]
Yeah, it was pretty messy. Just thinking out loud.
--
kevin kostrzewa
work: kkostrzewa@csisolutions.com
home: tkkost@newsguy.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/26 Raw View
On 25 Aug 99 19:14:30 GMT, Salters <salters@lucent.com> wrote:
>class Base {
>private:
> virtual A f();
>public:
> A do_f() {check_invariant();return f();}
>}
>class Derived {
> typeof(Base::f()) f();
>}
>
>Normally, we can't call Base::f, but we must use the same return type.
>typeof() provides us with (some) stability. Should this work?
>(Never mind the design of f() )
Clearly the following code is in error.
template <class T> void typeof(T t) { cout << typeid(t).name() << '\n'; }
int main() { typeof(Base::f()); }
If we follow Blargg's suggestion of struct typeof, and if we change C++
to allow the scope resolution operator to apply to a compound type,
then for the same reason the two lines above are in error, the one line
below is also in error
typeof(Base::f())::result f();
Recall that
template <class T> struct typeof { typedef T result; };
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/26 Raw View
blargg wrote:
>
> <tkkost@newsguy.com> wrote:
>
> > ...
> > If, as Siemel suggested,
> > :: could be applied to the return type of a function, typeof could be
> > written in terms of the language, but it would have to have a slightly
> > different syntax if you wanted the typeof an expression
>
> OK, type of an expression make sense.
>
> > vs. the typeof a type:
>
> Uhhh, I don't follow. Common-sense on. What the hell is "typeof a type"
> for? Typeof a type is the type. It's useless. I'll repeat what I posted a
> few days ago:
>
> typeof (typeof (typeof (typeof (typeof (typeof (typeof (int))))))))
>
While you don't need 'typeof <<type>>', it would make a bit more sense
in some cases to specify the types needed for a function signature
directly rather than having to supply an instance. Something like:
typeof func( class xyz)
which provides exactly the excuse needed to bring it closer to the
sizeof syntax. 'typeof (<<expr>>)' or typeof <<function signature>>.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/24 Raw View
In article <37C1B67F.B5B0B51A@cds.duke.edu>, Max TenEyck Woodbury
<mtew@cds.duke.edu> wrote:
> 'const' and 'volatile' are distinct attributes from the basic type
> of a data item. If they appear at the top level, they should be
> removed. After all, the main purpose of 'typeof' is to allow
> correctly typed copies to be instanced. One of the reasons for
> making the copy of something is to manipulate it in some way while
> leaving the original unchanged. Preserving 'const' at the top level
> could prevent this.
>
> In the one bad example given, some trouble was taken to throw away
> 'const' at a lower level.
>
> The original was
>
> > any_type foo;
> > typeof(foo)* bar = &foo;
> >
> > And now assume any_type is int const.
>
> The correct way to do this would be:
>
> any_type foo;
> typeof(&foo) bar = &foo;
>
> With any_type as int const, bar's type is * int const.
And one could remove the pointer and get a real const int from that:
template<typename T>
struct derefed_type;
template<typename T>
struct derefed_type<T*> {
typedef T type;
};
typename derefed_type<typeof (&foo)>::type bar = foo; // bar->const int
I'm still for object allowed on LHS of scope resolution operator :: that
typeof () could be implemented on top of by the user.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/24 Raw View
Lisa Lippincott <lisa_lippincott@advisories.com> writes:
> Here's a potential trouble spot with typeof: it allows a program to refer
> to unnamed classes and enums, which may cause havoc with linkage.
> Consider:
>
> enum {a};
> enum {b};
> void f( typeof(a) );
> void f( typeof(b) );
>
> What are the linkage names of the functions f?
Is the following illegal? Gcc compiles it without error or warning.
#include <iostream>
enum { a }; enum { b };
template <typename T> void f(T v) { cout << v << endl; }
int main() { f(a); f(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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/24 Raw View
In article <37C15129.B9D9255F@wizard.net>,
"James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
>
> "Siemel B. Naran" wrote:
>
> > On 19 Aug 1999 20:16:34 GMT, blargg
<postmast.root.admi.gov@iname.com> wrote:
> >
> > >This could be true, but why throw away information? The user can
always
> > >remove it if they want.
> >
> > On the other hand, they could always add the information if they
want.
>
> You can't add the information back once you've thrown it away. What
> you'd need would be yet another keyword, let's call it cvqual(T),
which
> returns a number indicating whether a top level 'const', 'volatile',
or
> both, would be thrown away by typeof(T).
The 'information' in question here is the reference qualifer,
not the const/volatile qualifer. This is unclear because the
article blargg was responding to has been cut, so here it is
again.
In article <37BBE6CC.FE2475E5@physik.tu-muenchen.de>, Christopher
Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
:: [...]
::
:: If we go to modify the variable, it only makes sense if we know
:: from the beginning that the function returns a reference. And
:: then we can put the reference litterally.
So, "why throw away information?" With regard to the reference
qualifier, Christopher has already answered that: because the
code that uses a variable or type *needs to know* whether it
is a reference; the reference qualifier should therefore be
explicit, not a variable that depends on some unknown.
As to const and volatile, we are in agreement. I have come
around to the view that these should be retained.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/24 Raw View
niklasb@my-deja.com writes:
> For example, instead of declaring std::find
> with two template parameters, as in
> template<class II, class T>
> II find(II begin, II end, const T& val);
> you could make T a function of II, thus:
> template<class II>
> II find(II begin, II end, typeof(const typeof(*II())& val));
This is very bad, because it is much too restrictive. In the good version
of find, val merely needs to be equality-comparable to a dereferenced II.
In your version, it must be of the same 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/24 Raw View
On 23 Aug 99 08:49:40 GMT, niklasb@my-deja.com <niklasb@my-deja.com> wrote:
> template<class II, class T>
> II find(II begin, II end, const T& val);
It is possible that T!=typeof(*II). Consider:
struct Silly { Silly(); };
struct Goofy { Goofy(); Goofy(Silly); };
and now,
void f(const std::container<Silly>& container) {
Goofy goofy;
std::find(container.begin(),container.end(),goofy);
}
The code for std::find is
II find(II begin, II end, const T& val) {
for ( ; begin!=end; ++begin) if (*begin==val) return begin;
return end;
} // typeof(*II)=="const Silly&" and T=="const Goofy&".
The compiler converts each element of the container from "const Silly&"
to "Goofy" in order to do the comparison (*begin==val).
> template<class II>
> II find(II begin, II end, typeof(const typeof(*II())& val));
Good.
But it is not identical with the original. In particular, the above
code fails because the compiler tries to convert 'goofy' from 'Goofy'
to 'Silly' and there is no such conversion.
However, the following code would work
void f(const std::container<Goofy>& container) {
Silly silly;
std::find(container.begin(),container.end(),silly);
} // convert 'silly' from 'Silly' to 'Goofy'
BTW, we also have the problem of two references in a row.
If II::operator*() returns "const T&".
Then "const typeof(*II)&" is "const const T& &".
We have this problem in std::bind1st and std::bind2nd.
>This allows for better parameter validation, and
>better diagnostics, because the compiler has more
>information about the parameter types.
Yes, this would be a most useful advantage.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/24 Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
> Here the deduction is being done by the argument type deduction for
> the `deduce<T>::operator()' function, rather than by `typeof()'.
So what? The point of having typeof is to let you do things that are
impossible to do otherwise. That it interacts synergistically with
other features of C++ is good, and in fact is an argument for adopting
it!
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/24 Raw View
In article <user-2308990741460001@as1-dialup-117.io.com>,
postmast.root.admi.gov@iname.com (blargg) wrote:
> In article <7pk70i$6as$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
>
> [snip]
>
> Did you put in an extra "typeof" here?
>
> template<class II>
> II find(II begin, II end, const typeof(*II())& val );
>
> Don't you mean this?
You're right, typo on my part.
> > This allows for better parameter validation, and
> > better diagnostics, because the compiler has more
> > information about the parameter types.
>
> This gives no extra information about the parameter types. It simply
> restricts them.
Isn't that the same thing? (When you restrict the domain
of a variable, you gain information about what the
variable can or cannot be.)
> > For example, the compiler could infer from the
> > declaration that the first two parameters must
> > be of a type that defines operator *. Thus, given
> > a call like
> >
> > find(0, 0, 0); // error: parameter 1: type 'int'
> > // does not define operator*
> >
> > the compiler could flag the first parameter as
> > an error -- at the call site.
>
> That's interesting, but considering the things it wouldn't check, I
don't
> like this inconsistency. For example, find probably needs operator ++
> defined, but that wouldn't be expressed in the interface.
True, if improved parameter validation for template
functions were the main goal of typeof, I'd have to
say it failed; but since it's merely a happy side-
benefit, it seems to me some error-checking is
better than none.
> > Similarly, given the first two parameters the
> > compiler would know the exact type of the third,
> > so given a call like
> >
> > vector<int> v;
> > double d = 1.0;
> > find(v.begin(), v.end(), d); // error: parameter 3:
> > // cannot convert 'double' to const int&
> >
> > the compiler could flag the third parameter as an
> > error -- again, at the call site.
>
> This is a new one to me, even using the current language definition!
Last
> time I checked, a const ref could be bound to a temporary.
Duh, got me again. Ok, substitute some other type for
which there is no conversion -- a string or another
iterator, say.
> > Without typeof, both of these errors would surface
> > only later, when instantiating the body of the
> > template function, and the compiler could not easily
> > know whether to attribute the error to the function
> > or its caller.
>
> But as I said, this is such inconsistent sparse checking, it's a false
> sense of usefulness.
I concede that typeof is not (and was not meant to be)
a complete solution to the problem of specifying the
constraints on template parameters.
My intent was merely to point out an interesting side-
benefit. I still think it would be kinda useful. The
false-sense-of-security argument can be taken too far,
as in, 'The compiler can never catch all programming
errors, so the fact that it catches any only engenders
a false sense of security.' :)
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/24 Raw View
In article <37C166A2.3029FB7F@lucent.com>,
Salters <salters@lucent.com> wrote:
> niklasb@my-deja.com wrote:
>
> > 3 Within the context of a typeof expression, a temporary
> > object of any type T can be instantiated using
>
> > - initialization notation, T(), whether or not
> > T has a default constructor, or
>
> > - cast notation, (T)expr, whether or not a
> > conversion from typeof(expr) to T exists.
>
> > (Because the expression is not evaluated, it does
> > not matter whether the temporary object can be
> > initialized correctly.)
>
> I think this is a bit uncalled for. Do you want
> typeof ((T) expr) to compile, if
> typeof ((T) expr) t=(T)expr doesn't? Why?
>
> I can see a need for T(), e.g. to be able to
> write:
> U func(T t) {...}
> typeof( func(T() ) ) u;
And the need for (T)expr is for exactly the same
purpose, e.g., to be able to write:
U func(T t) {...}
typeof( func( (T)0 ) ) u;
Someone told me in email that he preferred such cast
notation over initializer notation because it makes
it obvious that T is a type (rather than a function).
Regardless of which you prefer, it seems like the
language should permit either form.
> but perhaps we should allow
> typeof( func( typeof(T) ) ) u
> instead, or even allow
> typeof( func( T ) ) u; // as well as
> typeof( T ) t,
> i.e. make typeof(typename) equal to typename.
I initially proposed allowing typeof(type-id), mainly
just for parallelism with sizeof(type-id). But it would
serve no purpose, and in particular it would not obviate
the need for a way to create temporaries of any type, e.g.,
template<class T>
typeof(*T()) Func(T);
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/24 Raw View
On 23 Aug 99 20:32:16 GMT, blargg <postmast.root.admi.gov@iname.com> wrote:
>In article <7pk70i$6as$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
> template<class II>
> II find(II begin, II end, const typeof(*II())& val );
>> This allows for better parameter validation, and
>> better diagnostics, because the compiler has more
>> information about the parameter types.
>That's interesting, but considering the things it wouldn't check, I don't
>like this inconsistency. For example, find probably needs operator ++
>defined, but that wouldn't be expressed in the interface.
How about this
template<class II>
II find(II begin, II end, const typeof(*((++II())++))& val );
This says that II must have an accessible
default constructor
pre-increment
post-increment
operator*
Here's another idea
template<class II>
II find(II begin, II end, const typeof(++II,II++,*II)& val );
IOW, typeof(A,B,C) is the same as typeof(C). But then again, there
might be a A::operator,(B).
The direct approach might be better
template<class II, class T>
II find(II begin, II end, const T& val) [ ++II ] [ II++ ] [ *II ] ;
This says that we require operator++(II) or II::operator++(), etc.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: stanley@West.Sun.COM (Stanley Friesen [Contractor])
Date: 1999/08/24 Raw View
In article <slrn7rph2r.e43.sbnaran@localhost.localdomain>,
>The next question is what is more intuitive to use: that typeof throws
>away top level const and value/reference distinction, or retains it?
>
Answer: keeps const/volatile, throws away value/reference.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: 1999/08/23 Raw View
"Siemel B. Naran" wrote:
>
> On 19 Aug 1999 20:16:34 GMT, blargg <postmast.root.admi.gov@iname.com> wrote:
>
> >This could be true, but why throw away information? The user can always
> >remove it if they want.
>
> On the other hand, they could always add the information if they want.
You can't add the information back once you've thrown it away. What
you'd need would be yet another keyword, let's call it cvqual(T), which
returns a number indicating whether a top level 'const', 'volatile', or
both, would be thrown away by typeof(T).
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/23 Raw View
In article <slrn7rph2r.e43.sbnaran@localhost.localdomain>,
sbnaran@uiuc.edu wrote:
> On 19 Aug 1999 20:16:34 GMT, blargg <postmast.root.admi.gov@iname.com> wrote:
>
> >This could be true, but why throw away information? The user can always
> >remove it if they want.
>
> On the other hand, they could always add the information if they want.
That's a new one - recovering destroyed information. You should
immediately start working on a compression algorithm that does this.
You'll make millions. Imagine, compress anything to 0 bytes! Ahem.
> Or are there cases where they won't be able to do this? Think of
> examples where we use typeof in a template function.
That's exactly the point. I'm thinking about "filters" that go between the
arguments or return value of a caller and a function invocation. They want
to pass everything *exactly*, including reference types.
But I suppose this isn't really a problem with typeof in particular. The
same exists today with templates.
> The next question is what is more intuitive to use: that typeof throws
> away top level const and value/reference distinction, or retains it?
The real question is, is this convenience coming at the expense of some
power of typeof()?
> > typeof (ir)::type ir2 = ir;
>
> Great idea. I tried this program
>
> #include <iostream.h>
> template <class T> struct typeof_t { typedef T type; };
> template <class T> typeof_t<T> typeof(T) { abort(); }
> struct A { int a[3]; };
> int main()
> {
> A a;
> cout << sizeof(typeof(a)::type) << '\n'; // LINE 8
> }
>
> The EDG compilers tell me
> "type.cc", line 8: error: expected a ")"
> cout << sizeof(typeof(a)::type) << '\n'; // LINE 8
> ^
> As 'typeof' is a keyword in egcs, I had to replace "typeof" with
> "Typeof". Egcs gave me a parse error before "::" on LINE 8.
>
> So it appears that the scope resolution operator cannot be applied
> to return types of functions.
Uhhh, duhhh! :-) That was a proposed syntax by myself and Christopher
Eltschka. It is not currently valid. Must have been disappointing to have
it not compile :-(
> Which means that "typeof(thing)::type"
> can't work. I don't know whether the standard actually mandates
> this, but my guess is that it does. The question is why does the
> standard mandate this.
Because the scope resolution operator doesn't operate on objects on the LHS.
> I think that allowing "::" to be applied to the return types of
> functions but not introducing the 'typeof' keyword would be a
> better idea than introducing the 'typeof' keyword but leaving
> the "::" rules alone. Then we could implement struct typeof in
> terms of the existing core language.
Right. And it takes away the (agonizing :-) choice of what the type would
be. The rules of type deduction are determined by the template we use (if
we use one).
> This saves us the ordeal
> of figuring out the semantics of 'typeof'.
>
> In the previous post you said
>
> #define typeof(x) typeof(x)::type
[shouldn't it be
#define typeof(x) typename typeof(x)::type
?]
Yep. My brain isn't always fully conformant regarding typename :-)
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/23 Raw View
In article <7pk70i$6as$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
> An interesting thing about typeof is that in
> a template, you could express one type as a
> function of another type. This could allow for
> better parameter validation when calling
> template functions.
>
> For example, instead of declaring std::find
> with two template parameters, as in
>
> template<class II, class T>
> II find(II begin, II end, const T& val);
>
> you could make T a function of II, thus:
>
> template<class II>
> II find(II begin, II end, typeof(const typeof(*II())& val));
Did you put in an extra "typeof" here?
template<class II>
II find(II begin, II end, const typeof(*II())& val );
Don't you mean this?
> This allows for better parameter validation, and
> better diagnostics, because the compiler has more
> information about the parameter types.
This gives no extra information about the parameter types. It simply
restricts them.
> For example, the compiler could infer from the
> declaration that the first two parameters must
> be of a type that defines operator *. Thus, given
> a call like
>
> find(0, 0, 0); // error: parameter 1: type 'int'
> // does not define operator*
>
> the compiler could flag the first parameter as
> an error -- at the call site.
That's interesting, but considering the things it wouldn't check, I don't
like this inconsistency. For example, find probably needs operator ++
defined, but that wouldn't be expressed in the interface.
> Similarly, given the first two parameters the
> compiler would know the exact type of the third,
> so given a call like
>
> vector<int> v;
> double d = 1.0;
> find(v.begin(), v.end(), d); // error: parameter 3:
> // cannot convert 'double' to const int&
>
> the compiler could flag the third parameter as an
> error -- again, at the call site.
This is a new one to me, even using the current language definition! Last
time I checked, a const ref could be bound to a temporary.
> Without typeof, both of these errors would surface
> only later, when instantiating the body of the
> template function, and the compiler could not easily
> know whether to attribute the error to the function
> or its caller.
But as I said, this is such inconsistent sparse checking, it's a false
sense of usefulness.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Salters <salters@lucent.com>
Date: 1999/08/23 Raw View
niklasb@my-deja.com wrote:
> 3 Within the context of a typeof expression, a temporary
> object of any type T can be instantiated using
> - initialization notation, T(), whether or not
> T has a default constructor, or
> - cast notation, (T)expr, whether or not a
> conversion from typeof(expr) to T exists.
> (Because the expression is not evaluated, it does
> not matter whether the temporary object can be
> initialized correctly.)
I think this is a bit uncalled for. Do you want
typeof ((T) expr) to compile, if
typeof ((T) expr) t=(T)expr doesn't? Why?
I can see a need for T(), e.g. to be able to
write:
U func(T t) {...}
typeof( func(T() ) ) u;
but perhaps we should allow
typeof( func( typeof(T) ) ) u
instead, or even allow
typeof( func( T ) ) u; // as well as
typeof( T ) t,
i.e. make typeof(typename) equal to typename.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/23 Raw View
'const' and 'volatile' are distinct attributes from the basic type
of a data item. If they appear at the top level, they should be
removed. After all, the main purpose of 'typeof' is to allow
correctly typed copies to be instanced. One of the reasons for
making the copy of something is to manipulate it in some way while
leaving the original unchanged. Preserving 'const' at the top level
could prevent this.
In the one bad example given, some trouble was taken to throw away
'const' at a lower level.
The original was
> any_type foo;
> typeof(foo)* bar = &foo;
>
> And now assume any_type is int const.
The correct way to do this would be:
any_type foo;
typeof(&foo) bar = &foo;
With any_type as int const, bar's type is * int const.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Lisa Lippincott <lisa_lippincott@advisories.com>
Date: 1999/08/23 Raw View
Here's a potential trouble spot with typeof: it allows a program to refer
to unnamed classes and enums, which may cause havoc with linkage.
Consider:
enum {a};
enum {b};
void f( typeof(a) );
void f( typeof(b) );
What are the linkage names of the functions f?
This problem could be avoided by adding (perhaps to 3.5 paragraph 8)
Class and enum types without names shall not be used to declare
an entity with linkage, unless the type is defined in a typedef
declaration and has the typedef name for linkage purposes.
I think this statement follows from the current standard, but the
typeof proposal as it stands would allow it to be violated.
--Lisa Lippincott
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/23 Raw View
On 19 Aug 1999 20:16:34 GMT, blargg <postmast.root.admi.gov@iname.com> wrote:
>This could be true, but why throw away information? The user can always
>remove it if they want.
On the other hand, they could always add the information if they want.
Or are there cases where they won't be able to do this? Think of
examples where we use typeof in a template function.
The next question is what is more intuitive to use: that typeof throws
away top level const and value/reference distinction, or retains it?
> typeof (ir)::type ir2 = ir;
Great idea. I tried this program
#include <iostream.h>
template <class T> struct typeof_t { typedef T type; };
template <class T> typeof_t<T> typeof(T) { abort(); }
struct A { int a[3]; };
int main()
{
A a;
cout << sizeof(typeof(a)::type) << '\n'; // LINE 8
}
The EDG compilers tell me
"type.cc", line 8: error: expected a ")"
cout << sizeof(typeof(a)::type) << '\n'; // LINE 8
^
As 'typeof' is a keyword in egcs, I had to replace "typeof" with
"Typeof". Egcs gave me a parse error before "::" on LINE 8.
So it appears that the scope resolution operator cannot be applied
to return types of functions. Which means that "typeof(thing)::type"
can't work. I don't know whether the standard actually mandates
this, but my guess is that it does. The question is why does the
standard mandate this.
I think that allowing "::" to be applied to the return types of
functions but not introducing the 'typeof' keyword would be a
better idea than introducing the 'typeof' keyword but leaving
the "::" rules alone. Then we could implement struct typeof in
terms of the existing core language. This saves us the ordeal
of figuring out the semantics of 'typeof'.
In the previous post you said
#define typeof(x) typeof(x)::type
But now consider this
template <class T> struct A { A(){} };
template <class T> f(T t) { typeof(A<T>()) silly; }
the expansion is
template <class T> f(T t) { typeof(A<T>())::type silly; }
But shouldn't the expansion be
template <class T> f(T t) { typename typeof(A<T>())::type silly; }
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: stanley@West.Sun.COM (Stanley Friesen [Contractor])
Date: 1999/08/23 Raw View
In article <7phk8n$b26$1@nnrp1.deja.com>, <niklasb@my-deja.com> wrote:
>
>In article <user-1808991258230001@aus-as3-121.io.com>,
> postmast.root.admi.gov@iname.com (blargg) wrote:
>> > 3 When applied to a reference or a reference type,
>> > the result is the referenced type. When applied
>> > to a constant reference or constant reference type,
>> > the resulting type is not constant.
>>
>> Bad. Why not allow the user to decide to remove the reference?
>
>This is certainly an arguable point. ...
>
>I'm prepared to accept that my intuition may differ from
>the norm. It would be interesting to try both designs
>with a large number of programmers and find out which
>results in more surprises.
Personally, I think dropping reference is good, but dropping const/volatile
is bad.
As you say, in many cases, reference is intuitively best "ignored".
But the results of dropping const/volatile will more often be counter-
intuitive.
The basic argument is that a dropping these can make otherwise valid
assignments do something unexpected.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/23 Raw View
In article <37BD2185.C0047293@physik.tu-muenchen.de>,
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>
> [ snip ]
>
> I think top level const should be preserved (but I agree that
> reference should be removed).
>
> [ snip ]
>
> And my expectation would be that the following should
> always work:
>
> any_type foo;
> typeof(foo)* bar = &foo;
>
> And now assume any_type is int const.
You've convinced me. The reference should be stripped,
but the CV qualifier should be retained. Just to give
something concrete to talk about, let me try once again
to suggest a set of rules:
1 The typeof operator yields the type of its operand.
The operand is an expression, which is not evaluated.
The result is the CV-qualified type of the expression
(the static type, not the dynamic type of the object
returned by the expression).
<Example>
void func();
typeof(func)* fp = func;
</Example>
2 The typeof operator never yields a reference type.
When applied to a reference, the result is the
referenced type.
<Example>
vector<int> v(1);
typeof(v[0]) x = v[0]; // int x = v[0];
typeof(v[0])& y = v[0]; // int& y = v[0];
</Example>
3 Within the context of a typeof expression, a temporary
object of any type T can be instantiated using
- initialization notation, T(), whether or not
T has a default constructor, or
- cast notation, (T)expr, whether or not a
conversion from typeof(expr) to T exists.
(Because the expression is not evaluated, it does
not matter whether the temporary object can be
initialized correctly.)
4 In a variable declaration, the typeof operand can
be "...", representing the expression used to
initialize the variable.
<Example>
typeof(...) i = v.begin();
typeof(...) j( v.end() );
</Example>
Summary of changes:
- eliminated typeof(type-id), as it does nothing [1]
- result is now the CV-qualified type [1,2]
- added the rule about allowing arbitrary casts [3]
- added typeof(...), similar to proposed declare [4]
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/23 Raw View
Christopher Eltschka wrote:
>
> "Siemel B. Naran" wrote:
> >
> > On 13 Aug 99 15:52:23 GMT, Lisa Lippincott
> >
> > >/* what type goes here? */
> > >MultiplyAdd( const A& a, const B& b, const C& c )
> > > { return a * b + c; }
> >
> > In one of my posts I used this
> > typeof(A*B+C) MultiplyAdd(...) { ... }
>
> That's problematic:
>
> class X {};
> class Y { Y operator*(); };
> X operator*(X, Y);
> Y operator*(X*, Y);
>
> typeof(X**Y) a
>
> Is a of type X or of type Y?
> (That is, is the first star the multiplication operator and the
> second one the dereference operator, or is the first one part of
> the type, making a pointer to X, and the second one the
> multiplication operator?)
You need a slightly different syntax to distinguish the use of an
expression from the use of a type, as sizeof does. Since typeof
is not needed in the direct type specification case, it can be used
to get the type of function signatures. For example:
typedef typeof operator *(X,Y) XY; // = X
typedef typeof operator *(X*,Y) pXY; // = Y
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/23 Raw View
An interesting thing about typeof is that in
a template, you could express one type as a
function of another type. This could allow for
better parameter validation when calling
template functions.
For example, instead of declaring std::find
with two template parameters, as in
template<class II, class T>
II find(II begin, II end, const T& val);
you could make T a function of II, thus:
template<class II>
II find(II begin, II end, typeof(const typeof(*II())& val));
This allows for better parameter validation, and
better diagnostics, because the compiler has more
information about the parameter types.
For example, the compiler could infer from the
declaration that the first two parameters must
be of a type that defines operator *. Thus, given
a call like
find(0, 0, 0); // error: parameter 1: type 'int'
// does not define operator*
the compiler could flag the first parameter as
an error -- at the call site.
Similarly, given the first two parameters the
compiler would know the exact type of the third,
so given a call like
vector<int> v;
double d = 1.0;
find(v.begin(), v.end(), d); // error: parameter 3:
// cannot convert 'double' to const int&
the compiler could flag the third parameter as an
error -- again, at the call site.
Without typeof, both of these errors would surface
only later, when instantiating the body of the
template function, and the compiler could not easily
know whether to attribute the error to the function
or its caller.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/20 Raw View
On 19 Aug 1999 16:39:34 GMT, Christopher Eltschka
>"Siemel B. Naran" wrote:
>> In one of my posts I used this
>> typeof(A*B+C) MultiplyAdd(...) { ... }
>That's problematic:
>
>class X {};
>class Y { Y operator*(); };
>X operator*(X, Y);
>Y operator*(X*, Y);
>
>typeof(X**Y) a
The notation "X*" to mean pointer to an 'X' is wrong. One should say
"&X" to get a pointer to an 'X'. To summarize, "&X" means operator&
applied to an X object -- in short, X::operator&. An "*Y" means
operator* applied to a Y object -- in short, Y::operator*. So the
meaning is unamgiguous: typeof(X**Y) is simply X.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/20 Raw View
niklasb@my-deja.com wrote:
>
> In article <user-1808991258230001@aus-as3-121.io.com>,
> postmast.root.admi.gov@iname.com (blargg) wrote:
[...]
> >
> > > vector<int> v;
> > > typeof(v[0]) a; // int, not int&
> > >
> > > const vector<int>& cv = v;
> > > typeof(cv[0]) b; // int, not const int&
> >
> > And your example shows exactly why it shouldn't be that way.
>
> Our intuitions appear to differ. If p is an int*, what do you
> think typeof(*p) should be? (In any case, it should be spelled
> out, which I didn't do.)
>
> My feeling is that the result of the statement
>
> typeof(y) x = y;
>
> should always be that x is a copy of y, never that x is a
> reference to y. If you wanted the latter you could say:
>
> typeof(y)& x = y;
>
> > Like your argument (I think it was you) for not removing const, I
> argue
> > for not removing ref, since both can be done by the user with a
> template.
>
> You must be thinking of someone else.
Most probably he's thinking of my posting.
I think top level const should be preserved (but I agree that
reference should be removed).
> My feeling is that
> the "right-most" const/volatile qualifier should be removed:
>
> typeof((const int)0) // int
> typeof((int const* const)0) // int const*
>
> My reasoning is that a copy of a const or volatile object
> need not be const or volatile. However, a copy of a pointer
> to a const or volatile object must be a pointer to a const
> or volatile object. Example:
>
> char const* p = "foo";
> typeof(*p) ch = *p; // ch is a copy of *p
>
> My expectation here would be that ch is just a copy of the
> character p points to, and has type char (not const char
> or const char&). You could easily add const if needed.
And my expectation would be that the following should
always work:
any_type foo;
typeof(foo)* bar = &foo;
And now assume any_type is int const.
[...]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/18 Raw View
PLEASE check out the discussion of 'typeof' from September 1997!
niklasb@my-deja.com wrote:
>...
>
> Ok, here's my first crack at spelling out the rules for
> a "typeof" keyword (without attempting to argue for why
> it's useful). I don't claim to be a language designer, so
> please be gentle when you tear this apart.
>
> 1 The typeof operator yields the type of its operand.
> The operand is either an expression, which is not
> evaluated, or a parenthesized type-id.
>
> 2 When applied to an expression, the result is the type
> of the expression (the static type), not the dynamic
> type of the object returned by the expression.
>
> 3 When applied to a reference or a reference type,
> the result is the referenced type. When applied
> to a constant reference or constant reference type,
> the resulting type is not constant.
What about 'volatile'?
> <Example>
>
> vector<int> v;
> typeof(v[0]) a; // int, not int&
>
> const vector<int>& cv = v;
> typeof(cv[0]) b; // int, not const int&
>
> </Example>
>
> 4 The typeof operator can be applied to a function,
> a function pointer or a function pointer type.
All are expressions, so this only confuses things.
> <Example>
>
> int F();
> typedef int (*FPtr)();
>
> FPtr p0 = F;
> typeof(FPtr) p1 = F; // function ptr. type
> typeof(p1) p2 = F; // function ptr.
> typeof(&F) p3 = F; // function ptr.
> typeof(F)* p4 = F; // function
>
> </Example>
>
> 5 In the context of a typeof expression, if T is any
> type then T() denotes a temporary object of that
> type, even if the type has no default constructor.
> (The expression is not evaluated, so it does not
> matter whether the object can be correctly
> initialized.)
Wouldn't it make more sense to use (T)0, that is cast syntax,
rather than initializer syntax? That would be more consistent
with the argument being an expression. The comment about not
having to be correctly initialized is a useful addition and
needs to be incorporated.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/08/19 Raw View
niklasb@my-deja.com wrote:
....
> Ok, here's my first crack at spelling out the rules for
> a "typeof" keyword (without attempting to argue for why
> it's useful). I don't claim to be a language designer, so
> please be gentle when you tear this apart.
....
> 3 When applied to a reference or a reference type,
> the result is the referenced type. When applied
> to a constant reference or constant reference type,
> the resulting type is not constant.
Why? I'm not saying it's a bad idea, I just want to know why you think
it's a good one.
> <Example>
>
> vector<int> v;
> typeof(v[0]) a; // int, not int&
>
> const vector<int>& cv = v;
> typeof(cv[0]) b; // int, not const int&
>
> </Example>
Should this also apply to volatile?
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/19 Raw View
In article <7pcvjs$tk4$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
> In article <CVJFZFAbaWu3Ew15@robinton.demon.co.uk>,
> Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> >
> > [...]
> >
> > Proponents of 'typeof' should be beginning to get an idea of the
> degree
> > of detail required for a proposal for such a keyword. If and only if
> > they can provide a sufficiently tight specification some of us would
> be
> > willing to champion it, but if you want the extension in the next C++
> > standard they must do the preliminary work.
> >
> > [...]
>
> Ok, here's my first crack at spelling out the rules for
> a "typeof" keyword (without attempting to argue for why
> it's useful). I don't claim to be a language designer, so
> please be gentle when you tear this apart.
>
> 1 The typeof operator yields the type of its operand.
> The operand is either an expression, which is not
> evaluated, or a parenthesized type-id.
The latter refers to typeof (int) for example. What is that for?
> 2 When applied to an expression, the result is the type
> of the expression (the static type), not the dynamic
> type of the object returned by the expression.
I think some people were confused on this :-) This is one of those "duh" items.
> 3 When applied to a reference or a reference type,
> the result is the referenced type. When applied
> to a constant reference or constant reference type,
> the resulting type is not constant.
Bad. Why not allow the user to decide to remove the reference?
Bad. Call-through doesn't work.
int& func();
void g() {
typeof (func()) ret = func();
ret = 20; // oops, modified local variable ret
}
If they don't want the reference, they can remove it themselves:
template<typename T>
struct remove_ref {
typedef T type;
};
template<typename T>
struct remove_ref<T&> {
typedef T type;
};
void g() {
remove_ref<typeof (func())>::type ret = func(); // type is int
ret = 20; // OK, we know we made a copy
}
> vector<int> v;
> typeof(v[0]) a; // int, not int&
>
> const vector<int>& cv = v;
> typeof(cv[0]) b; // int, not const int&
And your example shows exactly why it shouldn't be that way.
Like your argument (I think it was you) for not removing const, I argue
for not removing ref, since both can be done by the user with a template.
Not that I think this construct is very good. Having to duplicate the
expression in many cases is just lame. I like "declare" ("var") much
better.
> 4 The typeof operator can be applied to a function,
> a function pointer or a function pointer type.
>
> int F();
> typedef int (*FPtr)();
>
> FPtr p0 = F;
> typeof(FPtr) p1 = F; // function ptr. type
Again, what is the purpose of allowing a type in typeof? It seems redundant.
typeof (typeof (typeof (typeof (typeof (typeof (int)))))) i = 1234;
> typeof(p1) p2 = F; // function ptr.
> typeof(&F) p3 = F; // function ptr.
> typeof(F)* p4 = F; // function
>
> 5 In the context of a typeof expression, if T is any
> type then T() denotes a temporary object of that
> type, even if the type has no default constructor.
> (The expression is not evaluated, so it does not
> matter whether the object can be correctly
> initialized.)
Joy. I don't like typeof in practice :-)
The closest to typeof that I think would be reasonable would be allowing
type members of a class to be referenced off a pointer/reference to the
object (with the lhs *not* being evaluated, since it could appear
anywhere):
template<class Container>
void f( Container& c ) {
for ( c.iterator p = c.begin(); c != c.end(); ++c ) {
// ...
}
}
To get typeof from this
template<typename T>
struct extract_type {
typedef T type;
};
template<typename T>
extract_type<T>& typeof( T& );
// use
typeof (foo).type foo_copy( foo );
Or, if one really wanted the same syntax,
#define typeof( expr ) typeof (expr).type
If we wanted to create temporaries of any type, just use a template:
template<typename T>
T temp();
typeof (temp<X>() + temp<Y>()) x = ...
Since the expression isn't evaluated, the template function definition
isn't needed.
I suppose declare could be derived fairly easily from this. Considering it
would be used for locals only (at least considering the simplest form of
the idea), a macro would allow the convenience:
#define declare( name, expr ) typeof (expr) name( expr )
// use
declare( foo_copy, (foo + 10) );
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/19 Raw View
"Siemel B. Naran" wrote:
>
> On 13 Aug 99 15:52:23 GMT, Lisa Lippincott
>
> >/* what type goes here? */
> >MultiplyAdd( const A& a, const B& b, const C& c )
> > { return a * b + c; }
>
> In one of my posts I used this
> typeof(A*B+C) MultiplyAdd(...) { ... }
That's problematic:
class X {};
class Y { Y operator*(); };
X operator*(X, Y);
Y operator*(X*, Y);
typeof(X**Y) a
Is a of type X or of type Y?
(That is, is the first star the multiplication operator and the
second one the dereference operator, or is the first one part of
the type, making a pointer to X, and the second one the
multiplication operator?)
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/19 Raw View
blargg wrote:
[...]
> > 3 When applied to a reference or a reference type,
> > the result is the referenced type. When applied
> > to a constant reference or constant reference type,
> > the resulting type is not constant.
>
> Bad. Why not allow the user to decide to remove the reference?
>
> Bad. Call-through doesn't work.
>
> int& func();
>
> void g() {
> typeof (func()) ret = func();
> ret = 20; // oops, modified local variable ret
> }
If we go to modify the variable, it only makes sense if we know
from the beginning that the function returns a reference. And
then we can put the reference litterally.
Indeed, if typeof makes the reference for us, it's even more
dangerous: change the function to return int instead int&,
and the compiler won't even warn us - if the reference is
explicit, it would complaion about binding an rvalue
to a non-const reference (if the return value gets const,
you get the error at the assignment line).
Note that this change may come as side effect if (erroneously)
making an object const, if func is an accessor into the
object, since often the accessors come in pairs like:
int& X::get() { ... }
int X::get() const { ... }
You _do_ want the compiler to warn you here, don't you?
>
> If they don't want the reference, they can remove it themselves:
>
> template<typename T>
> struct remove_ref {
> typedef T type;
> };
>
> template<typename T>
> struct remove_ref<T&> {
> typedef T type;
> };
>
> void g() {
> remove_ref<typeof (func())>::type ret = func(); // type is int
>
> ret = 20; // OK, we know we made a copy
> }
>
> > vector<int> v;
> > typeof(v[0]) a; // int, not int&
> >
> > const vector<int>& cv = v;
> > typeof(cv[0]) b; // int, not const int&
>
> And your example shows exactly why it shouldn't be that way.
>
> Like your argument (I think it was you) for not removing const, I argue
> for not removing ref, since both can be done by the user with a template.
I actually did that argument (But maybe I have missed the same
argument by someone else).
However, with references, it's more complicated:
int* p;
typeof(*p) foo = *p; // int foo = p, or int& foo = p?
Even the following is not entirely clear:
int i;
typeof(i) i2=i; // i is modifiable; should i2 be a reference?
What about:
int i;
int& i2 = i;
typeof(i2) i3 = i2;
// why should this case different from the previous?
The point is that references are defined to be "the same"
as the referenced variable - except on initialisation, there
is currently _no_ way to distinguish a reference from the
referenced type (except indirectly, by noting that other
variables change as well; however even then, you can't write
code that detects which one is the original and which one
is the reference). Making typeof reference-aware would break
that.
>
> Not that I think this construct is very good. Having to duplicate the
> expression in many cases is just lame. I like "declare" ("var") much
> better.
However, declare fails as soon as you get to return types
of functions (esp. if the definition is not in the current
translation unit):
// scalar product of two vectors
template<class T1, class T2>
typeof(T1() * T2()) operator*(Vector<T1> const&,
Vector<T2> const&);
[...]
> > 5 In the context of a typeof expression, if T is any
> > type then T() denotes a temporary object of that
> > type, even if the type has no default constructor.
> > (The expression is not evaluated, so it does not
> > matter whether the object can be correctly
> > initialized.)
>
> Joy. I don't like typeof in practice :-)
>
> The closest to typeof that I think would be reasonable would be allowing
> type members of a class to be referenced off a pointer/reference to the
> object (with the lhs *not* being evaluated, since it could appear
> anywhere):
>
> template<class Container>
> void f( Container& c ) {
> for ( c.iterator p = c.begin(); c != c.end(); ++c ) {
> // ...
> }
> }
>
> To get typeof from this
>
> template<typename T>
> struct extract_type {
> typedef T type;
> };
>
> template<typename T>
> extract_type<T>& typeof( T& );
>
> // use
>
> typeof (foo).type foo_copy( foo );
>
> Or, if one really wanted the same syntax,
>
> #define typeof( expr ) typeof (expr).type
Interesting point. So the object.type idiom would be
as powerful as the typeof idiom. (However, maybe the
syntax object::type would be preferrable, since in all
other cases, everything left of the "." is evaluated,
so the "." notation could cause confusion.). The rule
that nothing on the left of "::" is evaluated at run time
would be simple, and general (currently, nothing which
could possibly be evaluated at run time is allowed at all).
Being equally powerful, the "object scope" solution has
the advantage of not introducing a new keyword, and of
being more readable if a typedef is already provided,
as with c.iterator (or c::iterator).
[...]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/19 Raw View
In article <37BBDDCA.90D590D4@physik.tu-muenchen.de>, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
> "Siemel B. Naran" wrote:
> >
> > On 13 Aug 99 15:52:23 GMT, Lisa Lippincott
> >
> > >/* what type goes here? */
> > >MultiplyAdd( const A& a, const B& b, const C& c )
> > > { return a * b + c; }
> >
> > In one of my posts I used this
> > typeof(A*B+C) MultiplyAdd(...) { ... }
>
> That's problematic:
>
> class X {};
> class Y { Y operator*(); };
> X operator*(X, Y);
> Y operator*(X*, Y);
>
> typeof(X**Y) a
>
> Is a of type X or of type Y?
> (That is, is the first star the multiplication operator and the
> second one the dereference operator, or is the first one part of
> the type, making a pointer to X, and the second one the
> multiplication operator?)
As I said before (in case anyone missed it),
template<typename T> // heh, I almost typed "typeof" instead of "typename"
T make_type();
typeof (make_type<X>() * *make_type<Y>())
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/19 Raw View
In article <37BBE6CC.FE2475E5@physik.tu-muenchen.de>, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
> blargg wrote:
>
> [...]
>
> > > 3 When applied to a reference or a reference type,
> > > the result is the referenced type. When applied
> > > to a constant reference or constant reference type,
> > > the resulting type is not constant.
> >
> > Bad. Why not allow the user to decide to remove the reference?
> >
> > Bad. Call-through doesn't work.
> >
> > int& func();
> >
> > void g() {
> > typeof (func()) ret = func();
> > ret = 20; // oops, modified local variable ret
> > }
>
> If we go to modify the variable, it only makes sense if we know
> from the beginning that the function returns a reference. And
> then we can put the reference litterally.
This could be true, but why throw away information? The user can always
remove it if they want.
> Indeed, if typeof makes the reference for us, it's even more
> dangerous: change the function to return int instead int&,
> and the compiler won't even warn us - if the reference is
> explicit, it would complaion about binding an rvalue
> to a non-const reference (if the return value gets const,
> you get the error at the assignment line).
>
> Note that this change may come as side effect if (erroneously)
> making an object const, if func is an accessor into the
> object, since often the accessors come in pairs like:
>
> int& X::get() { ... }
> int X::get() const { ... }
>
> You _do_ want the compiler to warn you here, don't you?
I'm not sure how to solve this function problem.
> > If they don't want the reference, they can remove it themselves:
> >
> > template<typename T>
> > struct remove_ref {
> > typedef T type;
> > };
> >
> > template<typename T>
> > struct remove_ref<T&> {
> > typedef T type;
> > };
> >
> > void g() {
> > remove_ref<typeof (func())>::type ret = func(); // type is int
> >
> > ret = 20; // OK, we know we made a copy
> > }
With the proposed idea of being able to access type members (below),
typeof could do this automatically:
template<typename T>
remove_ref<T>& typeof( T& );
int i;
int& ir = i;
typeof (ir)::type ir2 = ir;
I think this would be best. It offers the flexibility of typeof while
being more intuitive (I know that people have asked why accessing types
off an object doesn't work).
It's funny, I came up with this idea partly because I caught my compiler
allowing it in one case!
f( foo->temp_lock() );
I thought temp_lock was a member func of foo, but it turns out it was a
type! The compiler was complaining about the type not having a default
ctor, when I realized it was allowing me to access a type off the pointer.
Bad compiler! Interesting idea :-)
> > > vector<int> v;
> > > typeof(v[0]) a; // int, not int&
> > >
> > > const vector<int>& cv = v;
> > > typeof(cv[0]) b; // int, not const int&
> >
> > And your example shows exactly why it shouldn't be that way.
> >
> > Like your argument (I think it was you) for not removing const, I argue
> > for not removing ref, since both can be done by the user with a template.
>
> I actually did that argument (But maybe I have missed the same
> argument by someone else).
> However, with references, it's more complicated:
>
> int* p;
> typeof(*p) foo = *p; // int foo = p, or int& foo = p?
Hmmm... I see your point. One should specifically ask for a reference if
they want one. The semantics of the expression would likely be known
enough, but there are still cases where the reference type of it should be
preserved (like the function example of returning exactly the same type it
returns).
> Even the following is not entirely clear:
>
> int i;
> typeof(i) i2=i; // i is modifiable; should i2 be a reference?
>
> What about:
>
> int i;
> int& i2 = i;
> typeof(i2) i3 = i2;
> // why should this case different from the previous?
>
> The point is that references are defined to be "the same"
> as the referenced variable - except on initialisation, there
> is currently _no_ way to distinguish a reference from the
> referenced type (except indirectly, by noting that other
> variables change as well; however even then, you can't write
> code that detects which one is the original and which one
> is the reference). Making typeof reference-aware would break
> that.
I still think the function "filter" is a problem. Uses of typeof should be
considered more, and problem situations identified.
I really like being able to access type members off an object. In many
cases, typeof isn't even needed (as in the container example).
> > Not that I think this construct is very good. Having to duplicate the
> > expression in many cases is just lame. I like "declare" ("var") much
> > better.
>
> However, declare fails as soon as you get to return types
> of functions (esp. if the definition is not in the current
> translation unit):
>
> // scalar product of two vectors
> template<class T1, class T2>
> typeof(T1() * T2()) operator*(Vector<T1> const&,
> Vector<T2> const&);
I like declare in its simple form, that is, for local variables. Nowhere
else (function params, return values, class members heh).
[snip]
> > The closest to typeof that I think would be reasonable would be allowing
> > type members of a class to be referenced off a pointer/reference to the
> > object (with the lhs *not* being evaluated, since it could appear
> > anywhere):
> >
> > template<class Container>
> > void f( Container& c ) {
> > for ( c.iterator p = c.begin(); c != c.end(); ++c ) {
> > // ...
> > }
> > }
> >
> > To get typeof from this
> >
> > template<typename T>
> > struct extract_type {
> > typedef T type;
> > };
> >
> > template<typename T>
> > extract_type<T>& typeof( T& );
> >
> > // use
> >
> > typeof (foo).type foo_copy( foo );
> >
> > Or, if one really wanted the same syntax,
> >
> > #define typeof( expr ) typeof (expr).type
>
> Interesting point. So the object.type idiom would be
> as powerful as the typeof idiom. (However, maybe the
> syntax object::type would be preferrable, since in all
> other cases, everything left of the "." is evaluated,
> so the "." notation could cause confusion.).
But what about a pointer to object? Would it have to be dereferenced first?
(*foo_ptr)::type
No?
foo_ptr::type
A pointer to pointer to object?
(**foo_ptr_ptr)::type
foo_ptr_ptr::type
How about a smart pointer? Oops, now we have to dereference it.
smart_ptr::type // sorry, smart_ptr doesn't have any members named type
(*smart_ptr)::type // OK
It's interesting, because essentially typeof is being implicitly applied
if we have an expression on the left side of ::
typeof (*foo_ptr)::type
What if, in a context where a type is needed, and an expression is given,
its static type is extracted and used? No, I'm not too serious, because I
imagine this would be a syntactic nightmare.
*foo_ptr x = *foo_ptr; // haha
foo foo2 = foo; // OK...
> The rule
> that nothing on the left of "::" is evaluated at run time
> would be simple, and general (currently, nothing which
> could possibly be evaluated at run time is allowed at all).
>
> Being equally powerful,
Right, as I more formally realize above.
> the "object scope" solution has
> the advantage of not introducing a new keyword, and of
> being more readable if a typedef is already provided,
> as with c.iterator (or c::iterator).
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/19 Raw View
In article <user-1808991258230001@aus-as3-121.io.com>,
postmast.root.admi.gov@iname.com (blargg) wrote:
> In article <7pcvjs$tk4$1@nnrp1.deja.com>, niklasb@my-deja.com wrote:
>
> [snip]
>
> >
> > 1 The typeof operator yields the type of its operand.
> > The operand is either an expression, which is not
> > evaluated, or a parenthesized type-id.
>
> The latter refers to typeof (int) for example. What is that for?
You're absolutely right. I thought of this too after I posted.
I would revise the first rule as follows:
1 The typeof operator yields the type of its operand.
The operand is an expression, which is not evaluated.
The result is the type of the expression (the static
type), not the dynamic type of the object returned
by the expression.
>
> > 2 When applied to an expression, the result is the type
> > of the expression (the static type), not the dynamic
> > type of the object returned by the expression.
>
> I think some people were confused on this :-) This is one of
those "duh" items.
Yes, but some people on this newsgroup have been confused
about this (even in the case of sizeof), so I thought
clarification necessary. Since it is just a clarification,
perhaps it should just be lumped under #1.
> > 3 When applied to a reference or a reference type,
> > the result is the referenced type. When applied
> > to a constant reference or constant reference type,
> > the resulting type is not constant.
>
> Bad. Why not allow the user to decide to remove the reference?
This is certainly an arguable point. Before responding to
your arguments, let me explain why I included this paragraph
in the first place.
My intuition says that if 'p' is an int* or an int[] then
typeof(*p) should be int. You could argue for int&, but I
suspect most people think of *p is denoting the integer
itself, not a refence to it.
Now suppose 'p' is, say, a vector<int>::iterator. Once
again, I would expect typeof(*p) to be int -- even though
the return type for the iterator's operator* is int&. This
is because the intuitive meaning of operator* is to take
an expression that denotes a pointer object and yield an
expression that denotes the thing pointed to. The '&' in
the return type is there simply to allow *p to appear on
the left-hand side of an assignment operator.
Every special case should be treated with suspicion, but
references are special in many ways. For example, sizeof
applied to a reference yields the size of the referenced
object, not the reference itself. This follows from the
idea that a reference is best thought of as a kind of
alias for another object rather than an object in its
own right. The proposed rule for typeof would parallel
the rule for sizeof on this respect.
I'm prepared to accept that my intuition may differ from
the norm. It would be interesting to try both designs
with a large number of programmers and find out which
results in more surprises.
> Bad. Call-through doesn't work.
>
> int& func();
>
> void g() {
> typeof (func()) ret = func();
> ret = 20; // oops, modified local variable ret
> }
This could be an oops, or it could be what you expect.
If typeof did yield an int&, I could very well be surprised
that changing ret also changed some other value. There is
nothing in function g() to suggest that ret is a reference
*unless* I look up the declaration of func().
> If they don't want the reference, they can remove it themselves:
>
> template<typename T>
> struct remove_ref {
> typedef T type;
> };
>
> template<typename T>
> struct remove_ref<T&> {
> typedef T type;
> };
>
> void g() {
> remove_ref<typeof (func())>::type ret = func(); // type is int
>
> ret = 20; // OK, we know we made a copy
> }
That is clever. But given the rule that typeof never yields
a reference type, it's much easier to add the reference
qualifier where needed:
void g() {
typeof(func())& ret = func();
ret = 20; // obviously modifying a reference
}
This makes it obvious that ret is a reference. We can also
tell -- looking only at g() -- that func() must return a
reference; otherwise assigning its return value to ret would
be illegal.
>
> > vector<int> v;
> > typeof(v[0]) a; // int, not int&
> >
> > const vector<int>& cv = v;
> > typeof(cv[0]) b; // int, not const int&
>
> And your example shows exactly why it shouldn't be that way.
Our intuitions appear to differ. If p is an int*, what do you
think typeof(*p) should be? (In any case, it should be spelled
out, which I didn't do.)
My feeling is that the result of the statement
typeof(y) x = y;
should always be that x is a copy of y, never that x is a
reference to y. If you wanted the latter you could say:
typeof(y)& x = y;
> Like your argument (I think it was you) for not removing const, I
argue
> for not removing ref, since both can be done by the user with a
template.
You must be thinking of someone else. My feeling is that
the "right-most" const/volatile qualifier should be removed:
typeof((const int)0) // int
typeof((int const* const)0) // int const*
My reasoning is that a copy of a const or volatile object
need not be const or volatile. However, a copy of a pointer
to a const or volatile object must be a pointer to a const
or volatile object. Example:
char const* p = "foo";
typeof(*p) ch = *p; // ch is a copy of *p
My expectation here would be that ch is just a copy of the
character p points to, and has type char (not const char
or const char&). You could easily add const if needed.
> Not that I think this construct is very good. Having to duplicate the
> expression in many cases is just lame. I like "declare" ("var") much
> better.
Declare would be nice, but would not eliminate the need
for typeof. Rather than add two new keywords, I like the
idea, suggested by someone else, of typeof(...), meaning
"the type of the initializer or rhs".
You would need typeof, rather than declare, to specify
the return type or a parameter type of a template
function. For example:
template<class II>
II find(II begin, II end, const typeof(*II())& val)
Because the third parameter's type is a function of
the iterator type, the compiler could do better
parameter validation when you call this template
function. The compiler knows something about the
expected type of the first parameter (it must define
operator*), and given the first two parameters it
knows the exact type of the third.
The following example shows how typeof(...) would be
used, and how typeof can allow for better validation
of template function parameters:
std::string fred("fred");
unsigned char ch = 'd';
typeof(...) imatch = find(fred.begin(), fred.end(), ch);
// Error: cannot convert parameter 3 from unsigned char to char
> > 4 The typeof operator can be applied to a function,
> > a function pointer or a function pointer type.
> >
> > int F();
> > typedef int (*FPtr)();
> >
> > FPtr p0 = F;
> > typeof(FPtr) p1 = F; // function ptr. type
>
> Again, what is the purpose of allowing a type in typeof? It seems
redundant.
>
> typeof (typeof (typeof (typeof (typeof (typeof (int)))))) i =
1234;
Yes, I agree.
> > typeof(p1) p2 = F; // function ptr.
> > typeof(&F) p3 = F; // function ptr.
> > typeof(F)* p4 = F; // function
> >
> > 5 In the context of a typeof expression, if T is any
> > type then T() denotes a temporary object of that
> > type, even if the type has no default constructor.
> > (The expression is not evaluated, so it does not
> > matter whether the object can be correctly
> > initialized.)
>
> Joy. I don't like typeof in practice :-)
>
> [snip]
The reason for this rule is to allow typeof to be used
where you don't have actual variables to work with, as
in the declaration of 'find' above. This is also the
reason a 'declare' feature would not be an adequate
substitute for typeof.
I think typeof would be valuable. Traits classes are
the existing alternative, but they make user code
syntactically more complex and place a greater burden
on library designers (because the library must define
the type relationships using typedefs, etc.) A typeof
operator would be easier to use, and would take
advantage of information the compiler already has.
--Nick
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/18 Raw View
In article <CVJFZFAbaWu3Ew15@robinton.demon.co.uk>,
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> [...]
>
> Proponents of 'typeof' should be beginning to get an idea of the
degree
> of detail required for a proposal for such a keyword. If and only if
> they can provide a sufficiently tight specification some of us would
be
> willing to champion it, but if you want the extension in the next C++
> standard they must do the preliminary work.
>
> [...]
Ok, here's my first crack at spelling out the rules for
a "typeof" keyword (without attempting to argue for why
it's useful). I don't claim to be a language designer, so
please be gentle when you tear this apart.
1 The typeof operator yields the type of its operand.
The operand is either an expression, which is not
evaluated, or a parenthesized type-id.
2 When applied to an expression, the result is the type
of the expression (the static type), not the dynamic
type of the object returned by the expression.
3 When applied to a reference or a reference type,
the result is the referenced type. When applied
to a constant reference or constant reference type,
the resulting type is not constant.
<Example>
vector<int> v;
typeof(v[0]) a; // int, not int&
const vector<int>& cv = v;
typeof(cv[0]) b; // int, not const int&
</Example>
4 The typeof operator can be applied to a function,
a function pointer or a function pointer type.
<Example>
int F();
typedef int (*FPtr)();
FPtr p0 = F;
typeof(FPtr) p1 = F; // function ptr. type
typeof(p1) p2 = F; // function ptr.
typeof(&F) p3 = F; // function ptr.
typeof(F)* p4 = F; // function
</Example>
5 In the context of a typeof expression, if T is any
type then T() denotes a temporary object of that
type, even if the type has no default constructor.
(The expression is not evaluated, so it does not
matter whether the object can be correctly
initialized.)
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/18 Raw View
"Siemel B. Naran" wrote:
>
> On 14 Aug 99 08:23:16 GMT, Christopher Eltschka
>
> > typeof(sin(x)/x + tan(x)*exp(-3*x*x))
> > expr = sin(x)/x + tan(x)*exp(-3*x*x);
>
> > declare expr = sin(x)/x + tan(x)*exp(-3*x*x);
>
> Can you think of a keyword other than 'declare'?
> It is highly possible that people have variables named 'declare'!
What about:
typeof(...) expr = sin(x)/x + tan(x)*exp(-3*x*x);
typeof(...) would be a placeholder for the type on the
right hand side of the expression. The "..." could be seen
as the omitted copy of the rhs expression.
Since ... is no expression, typeof(...) would otherwise
be illegal.
[...]
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/16 Raw View
On 13 Aug 99 15:52:23 GMT, Lisa Lippincott
>/* what type goes here? */
>MultiplyAdd( const A& a, const B& b, const C& c )
> { return a * b + c; }
In one of my posts I used this
typeof(A*B+C) MultiplyAdd(...) { ... }
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "David J. Littleboy" <davidjl@gol.com>
Date: 1999/08/16 Raw View
Andrew Koenig wrote in message ...
>Actually, it's much more profound than that: If we had "declare",
[snip]
>it would be possible to write
>
> declare copy(declare begin, declare end, declare out)
> {
> while (begin != end)
> *out++ = *begin**;
> return out;
> }
>
>Here, the type of the expression in the "return" statement would
>determine the return type of the function!
This one's been done before. It was a feature of BBN Lisp around 1972 called
DWIM: do what I mean.
David J. Littleboy
@ducking.for.cover.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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/16 Raw View
Salters <salters@lucent.com> writes:
>sirwillard@my-deja.com wrote:
>
>> In article <t7r9laz5hj.fsf@calumny.jyacc.com>,
>> Hyman Rosen <hymie@prolifics.com> wrote:
>> > Francis Glassborow <francis@robinton.demon.co.uk> writes:
>> > > In order to gain support you need to explain carefully (with
>> examples)
>> > > exactly what it is to do and what kind of non-academic problem it
>> will
>> > > solve. Code examples help.
>
>> > The basic problem it addresses is that there is no way, in general,
>> > to obtain the type of an expression as a typename that can be used
>> > in further declarations. This is especially a problem with templates.
>
>> Though I'd like the introduction of typeof, I feel someone should play
>> at least a bit of devils advocate. What should be the result of the
>> following?
>
>> base* p = new derived;
>> typeof(*p) copy(*p);
>
>A syntax error?
>
>Because typeof(*p) is a type, copy is taken to be a function returning
>a typeof(*p), but the argument list must contain a type for parameter *p.
I'm pretty sure that is not correct.
C++ compilers are expected to resolve such ambiguities.
If I write
int copy(*p);
that is a declaration of a variable `copy' initialized with `*p',
not a syntax error. Likewise, `typeof(*p) copy(*p)' should not be
a syntax error.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/16 Raw View
Gabriel Dos_Reis <gdosreis@korrigan.inria.fr> wrote in message
news:xajlnbfc920.fsf@korrigan.inria.fr...
> "Greg Brewer" <nospam.gregb@hal-pc.org> writes:
> | Consider one case, class Traits and class Traits_Record;
> | template <class T>
> | int StoreInDatabase(T *t)
> | {
> | // at this point, I needed a record. No way to declare one.
> | // perhaps typeof could be designed to handle the problem as follows
> | typeof(*t)##_Record record; // resolves to Traits_Record record;
>
> I don't think I'll support such an extension.
It occurs to me that I could acheive the same effect using a macro like
#define record(a,b) a##b
record(typeof(T),_Record) record;
I have tried simply using
record(T,_Record)
but was told type T_Record was unknown.
Greg Brewer
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/16 Raw View
On 13 Aug 99 17:17:14 GMT, Andrew Koenig <ark@research.att.com> wrote:
> template<class In, class Out>
> Out copy(In begin, In end, Out out)
> declare copy(declare begin, declare end, declare out)
Oops, what if typeof(end) is not the same as typeof(begin). The
original template version rejects this whereas the new declare
version accepts this. Not that I mind, though :).
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/16 Raw View
On 14 Aug 99 17:18:57 GMT, Gabriel Dos_Reis <gdosreis@korrigan.inria.fr> wrote:
>I don't think I'll support such an extension.
>Just an opinion.
At least give a reason.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/16 Raw View
Salters wrote:
>
> sirwillard@my-deja.com wrote:
> > What should be the result of the
> > following?
>
> > base* p = new derived;
> > typeof(*p) copy(*p);
>
> A syntax error?
Do you suggest that
int i (3);
should be a syntax error ?
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/16 Raw View
Hyman Rosen <hymie@prolifics.com> writes:
>fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>> However, `typeof' is not quite as general as argument type deduction.
>> For example, you may know that a particular variable has type
>> `foo<const T *>', and you may want to find out what `T' is;
>> you can do that with argument type deduction, but you can't do it
>> with `typeof'.
>
>Sure you can:
>
>template < typename T > struct foo;
>template < typename U > void call_with_foo(U my_foo_var)
>{
> // I know that my_foo_var is really a foo < const T * >
> struct deduce
> {
> template < typename T > T operator()(foo < const T *>);
> };
> typedef typeof(deduce()(my_foo_var)) my_T;
>}
Here the deduction is being done by the argument type deduction for
the `deduce<T>::operator()' function, rather than by `typeof()'.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1999/08/16 Raw View
Greg Brewer wrote:
...
> with extra text. Consider, a case I had. I had several structures defined
> in pairs. The first was the class I used through out my program and the
> second was a record class that was used to move data to/from a database.
> There was also operators defined for moving that data. A template was ideal
> for this operation.
>
> Consider one case, class Traits and class Traits_Record;
> template <class T>
> int StoreInDatabase(T *t)
> {
> // at this point, I needed a record. No way to declare one.
> // perhaps typeof could be designed to handle the problem as follows
> typeof(*t)##_Record record; // resolves to Traits_Record record;
> record.StoreData(t);
> return record.Write();
> }
That problem, at least, looks like something to be resolved with a
simple typedef, in each class, of the corresponding record class.
class Traits_Record;
class Traits
{
public:
typedef record_type Traits_record;
// The rest of your class definition
}
Then the line where you used ## could be replaced by:
typename T::record_type record;
typeof() may be a useful tool, but this isn't a case that calls for it.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/16 Raw View
ark@research.att.com (Andrew Koenig) writes:
>Fergus Henderson <fjh@cs.mu.OZ.AU> wrote:
>
>>I guess opinions differ here, but I certainly find the
>>syntax using `declare' to be much more pleasant to read.
>
>Actually, it's much more profound than that: If we had "declare",
>it would make it much, much easier to define many kinds of template
>functions. Having "typeof" wouldn't do it.
>
>For example, instead of
>
> template<class In, class Out>
> Out copy(In begin, In end, Out out)
> {
> while (begin != end)
> *out++ = *begin++;
> return out;
> }
>
>it would be possible to write
>
> declare copy(declare begin, declare end, declare out)
> {
> while (begin != end)
> *out++ = *begin**;
> return out;
> }
>
>Here, the type of the expression in the "return" statement would
>determine the return type of the function!
Perhaps you forgot the smiley? ;-)
I think the original idea with the `declare' proposal was that
an explicit initializer would be required. So it would not be allowed
on function return types or on function arguments, except perhaps
for arguments with default values.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/16 Raw View
Siemel B. Naran wrote:
> On 14 Aug 99 17:18:57 GMT, Gabriel Dos_Reis <gdosreis@korrigan.inria.fr> wrote:
>
> >I don't think I'll support such an extension.
> >Just an opinion.
>
> At least give a reason.
The reason why the mixture of template and preprocessor
uglyness should, and will be rejected should be obvious
to anyone.
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/16 Raw View
On 14 Aug 99 08:23:16 GMT, Christopher Eltschka
> typeof(sin(x)/x + tan(x)*exp(-3*x*x))
> expr = sin(x)/x + tan(x)*exp(-3*x*x);
> declare expr = sin(x)/x + tan(x)*exp(-3*x*x);
Can you think of a keyword other than 'declare'?
It is highly possible that people have variables named 'declare'!
To reduce the negative feeling about inventing a whole new keyword
for what really is a trivial feature, can you think of new name for
the keyword or a more general macro feature? Here are two
possibilities:
First
auto typeof expr = sin(x)/x + tan(x)*exp(-3*x*x);
Or
#define-> how sin(x)/x + tan(x)*exp(-3*x*x)
typeof(how) expr(how); 'how' available only to this line
typeof(how) error(how); // error: 'how' undefined
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Igor Boukanov <igor.boukanov@fi.uib.no>
Date: 1999/08/16 Raw View
Hyman Rosen wrote:
>
> You could use a potentially standard auxiliary class template:
>
> template < typename T > struct object { static T &o; };
>
> template < typename A, typename B, typename C >
> typeof(object<A>::o * object<B>::o + object<C>::o)
> MultiplyAdd(const A &a, const B &b, const C &c)
> {
> return a * b + c;
> }
>
> g++ 2.95, which implements typeof, gets an internal compiler error on this.
And g++ 2.95 also gets killed by
template <typename A, typename B, typename C>
typeof( (*(const A*)0) * (*(const B*)0) + (*(const C*)0) )
MultiplyAdd(const A &a, const B &b, const C &c)
{
return a * b + c;
}
Regards, Igor
--
Igor Boukanov
Company: Well Service Technology AS
Work: +47 5552 5075
Fax: +47 5552 5051 Web: http://www.wst.no/
Mobil: +47 916 28 390
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Gabriel Dos_Reis <gdosreis@korrigan.inria.fr>
Date: 1999/08/16 Raw View
sbnaran@uiuc.edu (Siemel B. Naran) writes:
| On 14 Aug 99 17:18:57 GMT, Gabriel Dos_Reis <gdosreis@korrigan.inria.fr> wrote:
|
| >I don't think I'll support such an extension.
| >Just an opinion.
|
| At least give a reason.
I am one of those who are convinced that Cpp must be destroyed.
Therefore I can't lobby for an extension that would be nothing more than
"yet another #pragma".
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/16 Raw View
James Kuyper <kuyper@wizard.net> wrote in message
news:37B82024.3E5A8013@wizard.net...
>
> Greg Brewer wrote:
> ...
> That problem, at least, looks like something to be resolved with a
> simple typedef, in each class, of the corresponding record class.
>
> class Traits_Record;
>
> class Traits
> {
> public:
> typedef record_type Traits_record;
>
> // The rest of your class definition
> }
I like your answer much better than mine. I did
class Traits
{
public:
Traits_record *Record(void) {return NULL;}
// The rest of your class definition
} ;
template <class X, class R>
int Store(X *x, R *r) {
R record;
record << *x;
...
}
template <class X>
int Store(X *x) {
return Store(x,x->Record());
}
Not only ugly, difficult to understand, but jumps around when tracing a call
with a debugger. However, it does work!
Greg Brewer
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/16 Raw View
Greg Brewer wrote:
>
>
> It occurs to me that I could acheive the same effect using a macro like
> #define record(a,b) a##b
>
> record(typeof(T),_Record) record;
>
> I have tried simply using
> record(T,_Record)
> but was told type T_Record was unknown.
>
The problem is that 'record' is processed by the preprocessor, before
typeof or template type deduction have been done.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/16 Raw View
In article <37B43D99.608A@wanadoo.fr>,
Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
>
> Siemel B. Naran wrote:
>
> > On 12 Aug 99 15:37:37 GMT, Valentin Bonnard <Bonnard.V@wanadoo.fr>
wrote:
> > >sirwillard@my-deja.com wrote:
> >
> > >> base* p = new derived;
> > >> typeof(*p) copy(*p);
> > >
> > >This one is easy: it's crystal-clear that it should create
> > >a base initialized with the derived object.
Not so crystal clear. The first thing that must be decided is
if 'typeof' performs static typing or runtime typing. Seems people
don't agree on this one within this thread. This is why I brought the
subject up... not because we can't come to a conclusion and define
proper semantics for it, but because the proper semantics have to be
defined in order to make a proposal.
> > it's crystal-clear that it should create
> > a base initialized with the base part of 'p', even if there
> > is a constructor base::base(const derived&). That is, we
> > have a call to base::base(const base&).
>
> The object passed to the ctor is still a derived object.
Is it? By dereferencing a base pointer, did I not slice the object?
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/17 Raw View
On 16 Aug 1999 23:20:20 GMT, sirwillard@my-deja.com
> Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
>> The object passed to the ctor is still a derived object.
>Is it? By dereferencing a base pointer, did I not slice the object?
There was no slicing as you passed by reference. To recap:
struct base { virtual ~base(); base(const base&); };
struct derived : base { };
base::base(const base& b) { assert(typeid(b)==typeid(derived); }
int main() { base * b=new derived; typeof(*b) copy(*b); delete b; }
The assertion will be true, at least in my rules of 'typeof'.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Salters <salters@lucent.com>
Date: 1999/08/17 Raw View
Valentin Bonnard wrote:
> Salters wrote:
> > sirwillard@my-deja.com wrote:
> > > What should be the result of the
> > > following?
> > > base* p = new derived;
> > > typeof(*p) copy(*p);
> > A syntax error?
> Do you suggest that
> int i (3);
> should be a syntax error ?
Of course not. However, lacking a formal syntax, I do not know
which *p are turned into types. That's why I put a question mark
after error. Thinking about it, I'm not sure how the formal syntax
should be, but it is reasonable to assume typeof() evaluates to a
type. This would definitely require some major standards work,
since currently nothing evaulates to a type.
Michiel Salters
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/17 Raw View
In article <slrn7rbkr7.dom.sbnaran@localhost.localdomain>, Siemel B.
Naran <sbnaran@uiuc.edu> writes
>Can you think of a keyword other than 'declare'?
_declare
Only implementors have to worry and they are in a better position to fix
the problem.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/17 Raw View
sirwillard@my-deja.com wrote:
>
> Not so crystal clear. The first thing that must be decided is
> if 'typeof' performs static typing or runtime typing. Seems people
> don't agree on this one within this thread. This is why I brought the
> subject up... not because we can't come to a conclusion and define
> proper semantics for it, but because the proper semantics have to be
> defined in order to make a proposal.
As originally proposed, typeof was the same kind of compiler construct
as sizeof. C's extension of sizeof to have a run-time component was not
then in train.
With that historical context, I think it is clear that typeof should
not have any run-time magic associated with it. That kind of magic belongs
to casts and typeid. The main reason for this is that types (as opposed
to instances) do not exist at run-time. Extending typeof to have a
run-time component would blur this semantic distinction.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/17 Raw View
Salters wrote:
> Valentin Bonnard wrote:
>
> > Salters wrote:
>
> > > sirwillard@my-deja.com wrote:
>
> > > > What should be the result of the
> > > > following?
>
> > > > base* p = new derived;
> > > > typeof(*p) copy(*p);
>
> > > A syntax error?
>
> > Do you suggest that
>
> > int i (3);
>
> > should be a syntax error ?
>
> Of course not. However, lacking a formal syntax, I do not know
> which *p are turned into types.
???
Obviously typeof(expr) designate a type while *p is an
expression.
> This would definitely require some major standards work,
> since currently nothing evaulates to a type.
???
int certainly does
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/17 Raw View
In article <37B908A8.717CAC2C@lucent.com>, Salters <salters@lucent.com>
writes
>Of course not. However, lacking a formal syntax, I do not know
>which *p are turned into types. That's why I put a question mark
>after error. Thinking about it, I'm not sure how the formal syntax
>should be, but it is reasonable to assume typeof() evaluates to a
>type. This would definitely require some major standards work,
>since currently nothing evaulates to a type.
Proponents of 'typeof' should be beginning to get an idea of the degree
of detail required for a proposal for such a keyword. If and only if
they can provide a sufficiently tight specification some of us would be
willing to champion it, but if you want the extension in the next C++
standard they must do the preliminary work.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/17 Raw View
Francis Glassborow wrote:
>
> Proponents of 'typeof' should be beginning to get an idea of the degree
> of detail required for a proposal for such a keyword. If and only if
> they can provide a sufficiently tight specification some of us would be
> willing to champion it, but if you want the extension in the next C++
> standard they must do the preliminary work.
>
You could start with the proposal I made in Sept 1997...
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1999/08/17 Raw View
Salters wrote:
>
> Valentin Bonnard wrote:
>
>> Salters wrote:
>>
>>> sirwillard@my-deja.com wrote:
>>>
>>>> What should be the result of the
>>>> following?
>>>>
>>>> base* p = new derived;
>>>> typeof(*p) copy(*p);
>>>
>>> A syntax error?
>>
>> Do you suggest that
>>
>> int i (3);
>>
>> should be a syntax error ?
>
> Of course not. However, lacking a formal syntax, I do not know
> which *p are turned into types. That's why I put a question mark
> after error. Thinking about it, I'm not sure how the formal syntax
> should be, but it is reasonable to assume typeof() evaluates to a
> type. This would definitely require some major standards work,
> since currently nothing evaulates to a type.
>
1. Not a syntax error, but a semantic diagnostic might be in order.
If the compiler tracks the right kind of information, the fact
that only part of the structure is being copied might be noted
in an informational message.
2. A macro can evaluate into anything, including a type. (re
another thread that raised questions about run-time behavior:
Macros are compile time only.) Template arguments are type
variables so why not a compile time type function? (And they are
compile time only.)
3a. There have been at least semi-formal proposals that indicate that
proper phrasing is feasible.
3b. The exact placement in the standard is a detail that should be left
to the standard committee, but it obviously belongs in the declaration
and types section of the standard rather than in the library section.
3c. The major problem is conceptual, and that is what this discussion is
working on. Translating the result into 'standard speak' should be
little different from adding any other feature to the standard.
mtew@cds.duke.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Lisa Lippincott <lisa_lippincott@advisories.com>
Date: 1999/08/13 Raw View
Here's an awkward fact about the typeof proposal: it seems useful within
a function, where there are lots of variables to make expressions from.
But it seems more difficult to use in a class definition or in
a function declaration, because there's no handy syntax for an
anonymous object of a given type. Consider:
template < class A, class B, class C >
/* what type goes here? */
MultiplyAdd( const A& a, const B& b, const C& c )
{ return a * b + c; }
Someone has already posted an example like this where the result type
is "typeof( A() * B() + C() )," but that requires the default constructors
of the types to be declared (implicitly or not) and accessible. The best
solution I've come up with which doesn't have such a restriction is
typeof( *(A*)(0) * *(B*)(0) + *(C*)(0) )
which seems less than elegant.
--Lisa Lippincott
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/13 Raw View
Hyman Rosen wrote:
> Jaakko Jdrvi <jaakko.jarvi@cs.utu.fi> writes:
> > If we had typeof, declare could be implemented as a macro (with
> > different syntax though):
> > #define DECLARE(VAR,EXPR) typeof(EXPR) VAR = EXPR
> > Consequently, the implementation should be
> > more or less straightforward.
>
> The C++ committee has adopted an Occam's Razor approach,
When ? References ?
> Given that declare is easily implementable given typeof,
> while typeof is not implementable in terms of declare, there is no chance
> that declare would be adopted.
How do you know ? Do you have a crystal ball ?
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Salters <salters@lucent.com>
Date: 1999/08/13 Raw View
sirwillard@my-deja.com wrote:
> In article <t7r9laz5hj.fsf@calumny.jyacc.com>,
> Hyman Rosen <hymie@prolifics.com> wrote:
> > Francis Glassborow <francis@robinton.demon.co.uk> writes:
> > > In order to gain support you need to explain carefully (with
> examples)
> > > exactly what it is to do and what kind of non-academic problem it
> will
> > > solve. Code examples help.
> > The basic problem it addresses is that there is no way, in general,
> > to obtain the type of an expression as a typename that can be used
> > in further declarations. This is especially a problem with templates.
> Though I'd like the introduction of typeof, I feel someone should play
> at least a bit of devils advocate. What should be the result of the
> following?
> base* p = new derived;
> typeof(*p) copy(*p);
A syntax error?
Because typeof(*p) is a type, copy is taken to be a function returning
a typeof(*p), but the argument list must contain a type for parameter *p.
I.e.
typeof(*p) copy (typeof(*p) rhs);
declares a function taking whatever type *p has, and returning an object
of the same type. This is of course not useful, but we cannot demand that
everywhere a construct is legal is is useful. ( the statement 5; comes to
mind).
Michiel Salters
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/13 Raw View
sirwillard@my-deja.com writes:
> Jaakko <jaakko.jarvi@cs.utu.fi> wrote:
>> See my example:
>> > typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
>> vs.
>> > declare x = a*b+c*d+e/f;
>> I find the first line less clear in intent.
>
>I don't.
Why not?
I guess opinions differ here, but I certainly find the
syntax using `declare' to be much more pleasant to read.
>Even if I agreed, however, I think the idiom to be poor.
>What you are doing is asking the compiler to determine the type of a
>complex expression and at the same time declare an instance of that
>type. If I can't determine the type at the time I write such a line,
>I'd hardly want the compiler to do so for me. There may be rare cases
>in which this is useful, but they are too rare to warrant yet another
>keyword when the typeof keyword gives the same identical functionality.
I disagree. Documenting the types adds verbosity; sometimes this
verbosity makes the code more readable, but sometimes it makes the code
less readable, because the actual code is hidden amongst all the type
annotations. If the types are complex template types, the increase
in verbosity from explicitly declaring the types of local variables may
make the code much less readable.
For maintenance, it's crucial to document the types of _interfaces_.
So it's important to declare the types for functions with external linkage.
For functions which are only used locally, it is not so important, but
still pretty useful. But documenting the types used in the body of a
function is much less important.
Many modern languages such as Haskell, ML, Mercury, etc. allow the compiler
to infer the types of local variables and functions. Mercury allows the
compiler to infer types for local variables and for functions local to
a module, but not for functions exported from a module. My experience
with programming in Mercury and Haskell is that declaring types for
functions is usually quite sufficient for readability; in these languages
it's very rare to want to explicitly declare the type for a local variable.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/13 Raw View
sbnaran@uiuc.edu (Siemel B. Naran) writes:
> I find this paragraph puzzling. Did you mean to say this: deduced
> types are available outside the function, but are not available
> within the function itself.
No, I meant what I said.
> It would be nice if we didn't have to always call an external
> function to take advantage of template argument deduction: it would
> be nice if deduced types were available within the function itself.
Yes, that's exactly what I meant! We are agreeing :-)
Deduced types are available within the called function,
but they are not available outside the called function,
say in the caller. Typeof corrects this.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/13 Raw View
Valentin Bonnard <Bonnard.V@wanadoo.fr> writes:
> Hyman Rosen wrote:
> > The C++ committee has adopted an Occam's Razor approach,
> When ? References ?
> > Given that declare is easily implementable given typeof,
> > while typeof is not implementable in terms of declare, there is no chance
> > that declare would be adopted.
> How do you know ? Do you have a crystal ball ?
I have seen commentary several times along the lines of "someone
suggested this extension, but then someone else showed how it
could be done in the current language, so the extension proposal
was dropped".
I assume that this will continue in the future. You are welcome
to laugh at me should I be proven wrong. (You can even join the
committee and lobby hard for declare just to prove me wrong :-)
Meanwhile, I will just continue to hold my narrow, closed-minded
belief that declare has a snowball's chance of being adopted.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/13 Raw View
Lisa Lippincott <lisa_lippincott@advisories.com> writes:
> Here's an awkward fact about the typeof proposal: it seems useful within
> a function, where there are lots of variables to make expressions from.
> But it seems more difficult to use in a class definition or in
> a function declaration, because there's no handy syntax for an
> anonymous object of a given type. Consider:
>
> template < class A, class B, class C >
> /* what type goes here? */
> MultiplyAdd( const A& a, const B& b, const C& c )
> { return a * b + c; }
You could use a potentially standard auxiliary class template:
template < typename T > struct object { static T &o; };
template < typename A, typename B, typename C >
typeof(object<A>::o * object<B>::o + object<C>::o)
MultiplyAdd(const A &a, const B &b, const C &c)
{
return a * b + c;
}
g++ 2.95, which implements typeof, gets an internal compiler error on this.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/13 Raw View
Fergus Henderson wrote:
> Valentin Bonnard <Bonnard.V@wanadoo.fr> writes:
> >Hyman Rosen wrote:
> >> If you think about it, there is a fundamental asymmetry in function
> >> template argument deduction, in that the deduced types are fully
> >> available to be used within the function,
> >
> >This ``asymmetry'' is called scoping, by the way.
> >
> >I am not sure that scoping has to be ``corrected''.
>
> `declare' and even `typeof' would both preserve scoping.
Note that I have never said that they wouldn't.
All I want to say is that the current asymmetry is
just the scoping asymmetry (that outside names are
visible inside but not the other way arround).
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/13 Raw View
Siemel B. Naran wrote:
> On 12 Aug 99 15:37:37 GMT, Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
> >sirwillard@my-deja.com wrote:
>
> >> base* p = new derived;
> >> typeof(*p) copy(*p);
> >
> >This one is easy: it's crystal-clear that it should create
> >a base initialized with the derived object.
>
> I disagree
Not really
> it's crystal-clear that it should create
> a base initialized with the base part of 'p', even if there
> is a constructor base::base(const derived&). That is, we
> have a call to base::base(const base&).
The object passed to the ctor is still a derived object.
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/13 Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
> However, `typeof' is not quite as general as argument type deduction.
> For example, you may know that a particular variable has type
> `foo<const T *>', and you may want to find out what `T' is;
> you can do that with argument type deduction, but you can't do it
> with `typeof'.
Sure you can:
template < typename T > struct foo;
template < typename U > void call_with_foo(U my_foo_var)
{
// I know that my_foo_var is really a foo < const T * >
struct deduce
{
template < typename T > T operator()(foo < const T *>);
};
typedef typeof(deduce()(my_foo_var)) my_T;
}
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/13 Raw View
<niklasb@my-deja.com> wrote in message news:7nt3vl$1oe$1@nnrp1.deja.com...
> Suppose I'm writing a template function and II is an unknown
> iterator type. How can I refer to the type one gets by
> dereferencing an II object?
>
> In many cases I could say II::value_type, but only if II is
> a class that contains a typedef for value_type. What if II is
> a simple pointer type? The use of the "typedef ... value_type"
> convention in the standard library only highlights the need
> for a more universal mechanism.
>
> I have in mind a keyword, typeof, which would yield the type
> of an expression. Like its cousin "sizeof," typeof would not
> actually evaluate anything at run-time.
>
> Does anyone else think such a keyword would be valuable? Or
> is this a solution in search of a problem? Following is a
> (somewhat contrived) example of how typeof might be used.
I think this typeof() function would be doublely useful if it could be used
with extra text. Consider, a case I had. I had several structures defined
in pairs. The first was the class I used through out my program and the
second was a record class that was used to move data to/from a database.
There was also operators defined for moving that data. A template was ideal
for this operation.
Consider one case, class Traits and class Traits_Record;
template <class T>
int StoreInDatabase(T *t)
{
// at this point, I needed a record. No way to declare one.
// perhaps typeof could be designed to handle the problem as follows
typeof(*t)##_Record record; // resolves to Traits_Record record;
record.StoreData(t);
return record.Write();
}
Just a consideration,
Greg Brewer
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/14 Raw View
ark@research.att.com (Andrew Koenig) writes:
> *Nothing* new is going to be adopted for a long time.
Sure, but eventually, there will be a new C++, like Ada 95 followed Ada 83.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/14 Raw View
Lisa Lippincott wrote:
>
> Here's an awkward fact about the typeof proposal: it seems useful within
> a function, where there are lots of variables to make expressions from.
> But it seems more difficult to use in a class definition or in
> a function declaration, because there's no handy syntax for an
> anonymous object of a given type. Consider:
>
> template < class A, class B, class C >
> /* what type goes here? */
> MultiplyAdd( const A& a, const B& b, const C& c )
> { return a * b + c; }
>
> Someone has already posted an example like this where the result type
> is "typeof( A() * B() + C() )," but that requires the default constructors
> of the types to be declared (implicitly or not) and accessible. The best
> solution I've come up with which doesn't have such a restriction is
>
> typeof( *(A*)(0) * *(B*)(0) + *(C*)(0) )
>
> which seems less than elegant.
You could make a declaration
template<class T> T obj();
Then you could write it as
template<class A, class B, class C>
typeof(obj<A>() * obj<B>() + obj<C>())
MultiplyAdd(A const& a, B const& b, C const& c)
{
return a*b+c;
}
Of course, if one invents a syntax for "an unnamed lvalue
of type T", only usable in typeof, then you could do a nicer
syntax:
template<class A, class B, class C>
typeof([A]*[B]+[C]) MultiplyAdd(A const& a, B const& b, C const& c)
{
return a*b+c;
}
However, I prefer being able to do something in an awkward syntax
to not being able to do it at all.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/14 Raw View
sirwillard@my-deja.com wrote:
>
> In article <37AFAC37.6B7F4253@cs.utu.fi>,
> Jaakko =?iso-8859-1?Q?J=E4rvi?= <jaakko.jarvi@cs.utu.fi> wrote:
> > Francis Glassborow wrote:
> > >
> > > with typeof you do not need declare, however declare would not
> provide
> > > all the utility of typeof, and is less clear in intent.
> >
> > I agree, that declare would not provide all the utility of typeof,
> > but I still think it would be useful (in addition to typeof).
> >
> > See my example:
> > > typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
> > vs.
> > > declare x = a*b+c*d+e/f;
> > I find the first line less clear in intent.
>
> I don't. Even if I agreed, however, I think the idiom to be poor.
> What you are doing is asking the compiler to determine the type of a
> complex expression and at the same time declare an instance of that
> type. If I can't determine the type at the time I write such a line,
> I'd hardly want the compiler to do so for me. There may be rare cases
> in which this is useful, but they are too rare to warrant yet another
> keyword when the typeof keyword gives the same identical functionality.
Think f.ex. of expression templates. There you can have
something like
void foo()
{
Placeholder x;
integrate(sin(x)/x, 1, 3);
}
Here sin(x)/x evaluates to a type like
Expression<Quotient<Sinus<Placeholder> >, Placeholder>
and integrate is a template on its first parameter.
Now, assume you want to compare the quality of two integration
routines on a complex expression, say sin(x)/x + tan(x)*exp(-3*x*x)
Now what is more clear (and less error prone):
double testinteg()
{
Placeholder x;
Expression<Sum<Quotient<Sinus<Placeholder>,Placeholder>,
Product<Tan<Placeholder>,
Exp<Times<Times<Constant<-3>,x>,x> > > > >
expr = sin(x)/x + tan(x)*exp(-3*x*x);
double result1 = integrate1(expr, 1, 3);
double result2 = integrate2(expr, 1, 3);
return (result1-result2)/result2;
}
or
double testinteg()
{
Placeholder x;
typeof(sin(x)/x + tan(x)*exp(-3*x*x))
expr = sin(x)/x + tan(x)*exp(-3*x*x);
// ...
}
or even
double testinteg()
{
Placeholder x;
declare expr = sin(x)/x + tan(x)*exp(-3*x*x);
// ...
}
I guess if making more use of templates, more of those
situations would arise.
[...]
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/14 Raw View
Hyman Rosen wrote:
>
> Francis Glassborow <francis@robinton.demon.co.uk> writes:
> > Likewise, if you can convince me that it is worthwhile, together with
> > the kind of material Dietmar suggested I would try to persuade the UK
> > C++ Panel (equivalent of J16) to support it. But you must put in the
> > work so that people like myself and Dietmar can argue for it.
>
> This is not anything like a formal proposal, but perhaps it's a
> starting point.
>
> Given
>
> namespace std
> {
> template<typename T> void __typeof__(volatile const T &);
> }
>
> I propose that the type of 'typeof(expr)' be defined to be the same
> as the deduced type of T in the call 'std::__typeof__(expr);'. The
> expression 'expr' is not evaluated.
>
> This semantics makes typeof of a reference be the same as typeof of
> its referrant, and discards top-level const and volatile, somewhat
> like the behavior of sizeof.
I'd prefer it to be the deduced type of
template<class T> void foo(T&)
i.e. it still contains the top level const/volatile, but discards
references.
It's not what g++ uses, but I've got surprised by g++ when
the following code wasn't OK:
int main()
{
int const i;
typeof(i)* pi = &i; // initialisation of int* with int const*!
}
Also note that if typeof gives the full cv qualified type, you
can still get the unqualified type with the following declarations:
template<class T> T discard_const(T const&);
template<class T> T discard_volatile(T volatile&);
template<class T> T discard_cv(T const volatile&);
typeof(discard_cv(expr)) foo;
// the same type as your typeof definition would result in
OTOH, I don't see a way how to re-create the const conce it was
discarded.
One could argue that the same should be true for references;
however, since references always act like the referenced object
(except on initialisation), it IMHO should do so with typeof as
well.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/14 Raw View
Andrew Koenig wrote:
> it would be possible to write
>
> declare copy(declare begin, declare end, declare out)
> {
> while (begin != end)
> *out++ = *begin**;
> return out;
> }
>
> Here, the type of the expression in the "return" statement would
> determine the return type of the function!
Will you also ask for discriminated unions, a more powerful
switch where cases bind variables (when applied to these
discriminated unions), gc, a way to syntaxically put
statements in expressions, syntaxic sugar to write (a,b)
instead of make_pair(a, b), currying, and general type
unification ?
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Gabriel Dos_Reis <gdosreis@korrigan.inria.fr>
Date: 1999/08/14 Raw View
"Greg Brewer" <nospam.gregb@hal-pc.org> writes:
[...]
| Consider one case, class Traits and class Traits_Record;
| template <class T>
| int StoreInDatabase(T *t)
| {
| // at this point, I needed a record. No way to declare one.
| // perhaps typeof could be designed to handle the problem as follows
| typeof(*t)##_Record record; // resolves to Traits_Record record;
I don't think I'll support such an extension.
Just an opinion.
[Moderator note: no me2 or yes/no votes followups please. --vb]
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/12 Raw View
In article <t7r9laz5hj.fsf@calumny.jyacc.com>,
Hyman Rosen <hymie@prolifics.com> wrote:
> Francis Glassborow <francis@robinton.demon.co.uk> writes:
> > In order to gain support you need to explain carefully (with
examples)
> > exactly what it is to do and what kind of non-academic problem it
will
> > solve. Code examples help.
>
> The basic problem it addresses is that there is no way, in general,
> to obtain the type of an expression as a typename that can be used
> in further declarations. This is especially a problem with templates.
Though I'd like the introduction of typeof, I feel someone should play
at least a bit of devils advocate. What should be the result of the
following?
base* p = new derived;
typeof(*p) copy(*p);
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/12 Raw View
sirwillard@my-deja.com wrote:
> Though I'd like the introduction of typeof, I feel someone should play
> at least a bit of devils advocate. What should be the result of the
> following?
>
> base* p = new derived;
> typeof(*p) copy(*p);
This one is easy: it's crystal-clear that it should create
a base initialized with the derived object.
The Devil's advocate strikes.
The Devil's advocate misses.
Valentin hits the Devil's advocate.
The Devil's advocate dies.
Do you want the Devil's advocate possessions identified ?
The Devil's advocate had a weak counter-argument when he died.
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/12 Raw View
In article <christian.bau-1108991021560001@christian-
mac.isltd.insignia.com>,
christian.bau@isltd.insignia.com (Christian Bau) wrote:
> In article <7opt86$pku$1@nnrp1.deja.com>, sirwillard@my-deja.com
wrote:
>
> > > See my example:
> > > > typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
> > > vs.
> > > > declare x = a*b+c*d+e/f;
> > > I find the first line less clear in intent.
> >
> > I don't. Even if I agreed, however, I think the idiom to be poor.
> > What you are doing is asking the compiler to determine the type of a
> > complex expression and at the same time declare an instance of that
> > type. If I can't determine the type at the time I write such a line,
> > I'd hardly want the compiler to do so for me. There may be rare cases
> > in which this is useful, but they are too rare to warrant yet another
> > keyword when the typeof keyword gives the same identical functionality.
>
> It is all about maintenance, and not forcing the programmer to specify
> things that he really doesnt care about. Say I want to exchange variables
> x and y. I need a temporary variable tmp. I dont want to specify the size
> of tmp, just "big enough".
>
> Anything that I have to specify is one thing that I can get right or
> wrong. Anything that I dont have to specify is one thing that I cannot get
> wrong. I prefer things that dont go wrong.
I see the "magic type" as being just as prone to error, but harder to
ascertain why. You've basically lessened type safety here.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/12 Raw View
sirwillard@my-deja.com writes:
> Though I'd like the introduction of typeof, I feel someone should play
> at least a bit of devils advocate. What should be the result of the
> following?
>
> base* p = new derived;
> typeof(*p) copy(*p);
The type of typeof(*p) is base. Typeof, like sizeof, is based only on
the static type of the expression. It's a compile-time construct.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/12 Raw View
On 11 Aug 99 17:46:58 GMT, Hyman Rosen <hymie@prolifics.com> wrote:
>template < typename Creator >
>vector < typeof(Creator()(0)) > make_vector(Creator c, int n)
>{
> vector < typeof(c(0)) > v;
> for (int i = 0; i < n; ++i)
> v.push_back(c(i));
> return v;
>}
>
>int f(int n) { return n * n; }
>
>int main()
>{
> vector < int > v = make_vector(f, 10);
> return v[0];
>}
Well, the 'typeof' keyword is not really necessary here. In fact,
it might be better to do this without the typeof. Consider:
struct Square : std::unary_function<int,int> {
result_type operator()(argument_type arg) const { return arg*arg; }
};
And your 'make_vector' function:
template < typename Creator >
vector < typename Creator::result_type > make_vector(Creator c, int n)
I had an example very similar to this.
Adding a int to double yields a double.
So adding a Complex<int> to Complex<double> should yield a Complex<double>.
So we write:
template <class T1, class T2>
Complex<typeof(T1+T2)> operator+(Complex<T1>,Complex<T2>);
(Most likely, the implementation of the above function relies on the
existence of templated copy constructor to convert a Complex<int> into
a Complex<double> (which class std::complex<> does not have), but that
is another matter.)
Without the typeof keyword we can do this.
template <class T1, class T2> struct add { typedef void result; };
template <> struct add<int,double> { typedef double result; }
template <> struct add<double,int> { typedef double result; }
And finally
template <class T1, class T2>
typename add<T1,T2>::result operator+(Complex<T1>,Complex<T2>);
The syntax is cumbersome. Moreover, it requires clients to define
specializations of add for each class they write. First of all, this
is tedious. Second of all, it is not generally possible: When we
write a class X, how do we know what utility structs to specialize?
Maybe we'll buy a third party library one year from now, and that
library requires us to specialize std2::add and std2::subtract. So
now we have to rewrite our good old class X. Then later we might
have to specialize std2::Add or std3::add, because some third party
library uses these names.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/13 Raw View
Valentin Bonnard <Bonnard.V@wanadoo.fr> writes:
> Hyman Rosen wrote:
> > If you think about it, there is a fundamental asymmetry in function
> > template argument deduction, in that the deduced types are fully
> > available to be used within the function,
>
> This ``asymmetry'' is called scoping, by the way.
> I am not sure that scoping has to be ``corrected''.
This has nothing to do with scoping. Function template argument deduction
is done by the compiler using types that are completely *external* to the
function template.
If I write the following -
template < typename R, typename A > A arg1_type(R (*)(A));
double my_conv(int);
int main()
{
int a = arg1_type < double, int >(my_conv);
int b = arg1_type(my_conv);
typeof(arg1_type(my_conv)) c = arg1_type(my_conv);
}
In no case am I using types defined inside the function template arg1_type.
I am simply asking for a way to get at the types for R and A that the
compiler has deduced from the function call. This is particularly important
when the code that needs this information is itself a template which is
trying to "pass through" some type derived from one of its own template
arguments.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/13 Raw View
On 12 Aug 99 15:26:43 GMT, sirwillard@my-deja.com
>Though I'd like the introduction of typeof, I feel someone should play
>at least a bit of devils advocate. What should be the result of the
>following?
>
>base* p = new derived;
>typeof(*p) copy(*p);
This 'typeof' thing is entirely compile time, as opposed to 'typeid'
which is compile time or run time. Hence "typeof(*p)" is "base".
base * p=new derived;
base copy(p);
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/13 Raw View
On 12 Aug 99 15:37:37 GMT, Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
>sirwillard@my-deja.com wrote:
>> base* p = new derived;
>> typeof(*p) copy(*p);
>
>This one is easy: it's crystal-clear that it should create
>a base initialized with the derived object.
I disagree : it's crystal-clear that it should create
a base initialized with the base part of 'p', even if there
is a constructor base::base(const derived&). That is, we
have a call to base::base(const base&).
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/13 Raw View
On 12 Aug 99 14:15:00 GMT, Hyman Rosen <hymie@prolifics.com> wrote:
>If you think about it, there is a fundamental asymmetry in function
>template argument deduction, in that the deduced types are fully
>available to be used within the function, including declaring new
>variables of the deduced types and derivations based on them, but
>there is no way to use such a deduced type *outside* the function.
I find this paragraph puzzling. Did you mean to say this: deduced
types are available outside the function, but are not available
within the function itself. With code:
template <class Thing> silly(Thing t) { ... }
void f() { silly(std::bind2nd(std::plus<int>(),5)); }
We see that the type of "std::bind2nd(std::plus<int>(),5)" is fully
available to the external function 'silly'.
It would be nice if we didn't have to always call an external
function to take advantage of template argument deduction: it would
be nice if deduced types were available within the function itself.
Then we could say
void f() { typeof(expr) t(expr); ... }
where 'expr' is "std::bind2nd(std::plus<int>(),5)". Now we can
use 't' inside the body of the function 'f'. Without the typeof
keyword I have to figure out the type of 't' myself. Let me
give it a shot:
typeof(t)==std::binder2nd<std::plus<int>>
Not so hard. But what if we had longer expressions using
std::compose, std::mem_fun, and stuff we may write ourselves?
Incidentally, the code
declare t=std::bind2nd(std::plus<int>(),5);
is very useful. But to avoid having to create a new keyword we
can do this:
#define expr=std::bind2nd(std::plus<int>(),5);
typeof(expr) t=expr;
#undef expr
>It is this asymmetry which typeof corrects.
Agreed.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/08/13 Raw View
Valentin Bonnard <Bonnard.V@wanadoo.fr> writes:
>Hyman Rosen wrote:
>
>> If you think about it, there is a fundamental asymmetry in function
>> template argument deduction, in that the deduced types are fully
>> available to be used within the function,
>
>This ``asymmetry'' is called scoping, by the way.
>
>I am not sure that scoping has to be ``corrected''.
`declare' and even `typeof' would both preserve scoping.
I think it's more an issue of orthogonality rather than asymmetry.
Type deduction and function calls are separate things. C++ compilers
know how to do type deduction, and knows how to do function calls.
But for various reasons, mostly historical IMHO, C++ doesn't provide
any way to do type deduction without doing a function call.
`typeof' could remedy that.
However, `typeof' is not quite as general as argument type deduction.
For example, you may know that a particular variable has type
`foo<const T *>', and you may want to find out what `T' is;
you can do that with argument type deduction, but you can't do it
with `typeof'.
Still, `typeof' is a simple extension in the following senses:
- it's easy to implement (C++ compilers already have the necessary
infrastructure for doing type deduction, so I think it should
basically be just a matter of adding the front-end syntax)
- it's easy to specify
- it's easy for programmers to understand
I'm not sure how useful it is, but as far as extensions go,
the cost of adding this one is very low.
--
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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: niklasb@my-deja.com
Date: 1999/08/04 Raw View
Suppose I'm writing a template function and II is an unknown
iterator type. How can I refer to the type one gets by
dereferencing an II object?
In many cases I could say II::value_type, but only if II is
a class that contains a typedef for value_type. What if II is
a simple pointer type? The use of the "typedef ... value_type"
convention in the standard library only highlights the need
for a more universal mechanism.
I have in mind a keyword, typeof, which would yield the type
of an expression. Like its cousin "sizeof," typeof would not
actually evaluate anything at run-time.
Does anyone else think such a keyword would be valuable? Or
is this a solution in search of a problem? Following is a
(somewhat contrived) example of how typeof might be used.
template<class II>
II FindEndQuote(II isz)
{
typedef typeof(*isz) Ch;
Ch quote = *isz;
do {
++isz;
} while (*isz != quote && *isz != Ch(0));
return isz;
}
char* Foo(char* psz)
{
return FindEndQuote(psz);
}
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dietmar Kuehl <dietmar.kuehl@claas-solutions.de>
Date: 1999/08/04 Raw View
Hi,
In article <7nt3vl$1oe$1@nnrp1.deja.com>,
niklasb@my-deja.com wrote:
> Suppose I'm writing a template function and II is an unknown
> iterator type. How can I refer to the type one gets by
> dereferencing an II object?
That one is easy:
template <typename II, typename value_type>
void foo(II it, value_type*) {
value_type val = *it;
...
}
template <typename II>
void foo(II it) {
foo(it, &*it);
}
However, it becomes more interesting if you want to use the value type
in a class rather than in a function because in this case you cannot use
the above trick.
Currently, the standard supports iterator traits which do part of this for
iterators:
template <typename II>
class foo {
typename std::iterator_traits<II>::value_type value_type;
...
};
However, this would require that the iterator traits are specialized for the
iterator class in question. Also, it only applies to iterators not for other
kinds of abstractions.
Although this problem can be solved using this traits mechanism with
the current language, it would be reasonable to have something like
the 'typeof' keyword you suggested in the language. At minimum it
saves most of the need for creating traits classes by giving access to
information which is available to the compiler anyway. However, there
is still some need for the traits classes eg. to specify the iterator category
the class falls into.
--
<mailto:dietmar.kuehl@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/05 Raw View
On 04 Aug 99 10:09:10 GMT, niklasb@my-deja.com <niklasb@my-deja.com> wrote:
>Suppose I'm writing a template function and II is an unknown
>iterator type. How can I refer to the type one gets by
>dereferencing an II object?
>
>In many cases I could say II::value_type, but only if II is
>a class that contains a typedef for value_type. What if II is
>a simple pointer type? The use of the "typedef ... value_type"
>convention in the standard library only highlights the need
>for a more universal mechanism.
One should use std::iterator_traits<> for this.
template <class Iter>
typename std::iterator_traits<Iter>::value_type
sum(Iter begin, const Iter end) {
typedef typename std::iterator_traits<Iter>::value_type Value;
Value v=Value();
while (begin!=end) v+=*iter++;
return v;
}
Three problems with this:
[X] it looks ugly -- we prefer to write "typename Iter::value_type Value"
[X] it looks ugly -- we prefer to write "typename Iter::value_type Value"
[X] library writers have to remember to specialize std::iterator_traits<>
I see two solutions:
[X] Make a class std::iter<T> that is a proxy for a T* and that adds
nested typedefs value_type and difference_type and so on, and
require std::vector<T>::iterator to use this proxy class. On a
fully optimizing compiler, there will be no overhead for doing
this.
[X] Add the typedefs value_type and difference_type and so on to
the builtin pointers. It may sound weird, but it will not break
existing code. So I think this change should be written into
the standard.
>I have in mind a keyword, typeof, which would yield the type
>of an expression. Like its cousin "sizeof," typeof would not
>actually evaluate anything at run-time.
It won't work flawlessly for your case. Be aware that the 'sum' example
I wrote above works for the common case of Iter==const_iterator -- try it
with std::list<int>::const_iterator. Note that
iterator<T>::value_type == T
const_iterator<T>::value_type == T // note: not "const T"
Hence the following code
template <class Iter>
typeof(*Iter)
sum(Iter begin, const Iter end) {
typedef typeof(*Iter) Value;
Value v=Value();
while (begin!=end) v+=*iter++;
return v;
}
does not work for the common case of Iter=="double const *" because
Value is "const double".
>Does anyone else think such a keyword would be valuable? Or
>is this a solution in search of a problem? Following is a
>(somewhat contrived) example of how typeof might be used.
The typeof keyword is still a good idea. Being able to say
"typeof(*Iter)" as above will doubtless be useful on ocassion.
The typeof keyword can be used for things like this:
typedef typeof(bind1st(plus<int>(),5)) Silly;
... use Silly ...
And finally, the typeof keyword helps us deal with old code
that wasn't written with excessive typedefing.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/08/06 Raw View
In article <7nt3vl$1oe$1@nnrp1.deja.com>,
niklasb@my-deja.com wrote:
> I have in mind a keyword, typeof
Cool. Siemel Naran and I are two loud proponents of it. Some have
constantly "proven" us that either it can be easily simulated with the
current language (it's not), that it's hard to implement (it's not), or
that it wouldn't solve any real problem (it would).
The only way you can partially simulate it is via traits and partial
specialization, which is clumsy, unintuitive, and potentially
incomplete. (You have iterator_traits, but not container_traits,
type_traits, ...)
Andrei
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/06 Raw View
In article <7oa71e$uju$1@nnrp1.deja.com>, Andrei Alexandrescu
<andrewalex@hotmail.com> writes
>Cool. Siemel Naran and I are two loud proponents of it. Some have
>constantly "proven" us that either it can be easily simulated with the
>current language (it's not), that it's hard to implement (it's not), or
>that it wouldn't solve any real problem (it would).
I think that a useful way forward is to persuade a couple of good
implementers to provide typeof as an extension. If it is done soon
enough a body of experience can be built up that will support its formal
standardisation some time in the next millennium.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/08/06 Raw View
Francis Glassborow wrote:
> I think that a useful way forward is to persuade a couple of good
> implementers to provide typeof as an extension. If it is done soon
> enough a body of experience can be built up that will support its
formal
> standardisation some time in the next millennium.
Well, egcs/gcc has it already so that is a good start. :-)
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: rado42 <rado42@my-deja.com>
Date: 1999/08/08 Raw View
There has always been a discussion about 'typeof' proposal
fiew months ago. If interested, you might search for it.
I use this opportunity to express my support FOR the idea again.
I suggest to vote for or against it it. We could do it like this:
Anyone who is FOR the 'typedef' extension, reply to this mail.
Anyone AGAINST it, reply to the 1st one that is AGAINST it.
--
rado
http://members.tripod.com/~radosoft
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/09 Raw View
rado42 wrote:
>
> There has always been a discussion about 'typeof' proposal
> fiew months ago. If interested, you might search for it.
>
> I use this opportunity to express my support FOR the idea again.
>
> I suggest to vote for or against it it. We could do it like this:
>
> Anyone who is FOR the 'typedef' extension, reply to this mail.
^^^^^^^
Should be 'typeof', right?
FOR!
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/09 Raw View
On 08 Aug 99 17:22:20 GMT, rado42 <rado42@my-deja.com> wrote:
>I suggest to vote for or against it it. We could do it like this:
>
>Anyone who is FOR the 'typedef' extension, reply to this mail.
>Anyone AGAINST it, reply to the 1st one that is AGAINST it.
This won't work because there are a lot of smart people who don't
read the newsgroups.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: kuehl@horn.fmi.uni-konstanz.de (Dietmar Kuehl)
Date: 1999/08/09 Raw View
Hi,
rado42 (rado42@my-deja.com) wrote:
: I suggest to vote for or against it it.
To what end? The standard was approved last year and will remain stable
until at least 2003. Of course, we may lobby our favorite compiler
provider to implement this feature and we might even get several
providers to implement this feature exactly the same. It is even
implemented by existing compilers eg. I know that g++ at least had this
feature for some years. [Dietmar is checking whether the features is
still there] Cool: gcc still has it.
So, we should demonstrate useful application of this keyword, show
where things become possible which were not possible before and/or much
easier to warrent this feature. If we can provide evidence that this
feature is needed by showing the difference of the code with and
without this feature, I can imagine that for the next round of
standardization we can get it in.
: Anyone who is FOR the 'typedef' extension, reply to this mail.
: Anyone AGAINST it, reply to the 1st one that is AGAINST it.
Go to the meetings of the corresponding national body and/or to the
joint ANSI/ISO meetings and talk to people trying to convince them of
the usefulness of this feature. Write a proposal for this feature
(saying what it does, where it is useful, what the impacts are, which
code is broken, and spelling out the details how to change the
standard). This has better chance to get the feature in than having a
vote on the Net! I'm also willing to push this issue forward
(potentially trying to get the German body into a position of rejecting
the next version of the Standard, that is after 2003, if this feature
is not in). But I don't have the necessary insight into the core
language to write the corresponding proposal... Maybe there is already
a proposal which was just received to late? Whas it voted on?
--
<mailto:dietmar.kuehl@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jaakko =?iso-8859-1?Q?J=E4rvi?= <jaakko.jarvi@cs.utu.fi>
Date: 1999/08/09 Raw View
rado42 wrote:
>
> There has always been a discussion about 'typeof' proposal
> fiew months ago. If interested, you might search for it.
>
While we are at it, let's take this further.
I remember seeing someone suggest (in addtion to typeof)
'declare' keyword:
declare x = some_expression;
The semantics is to declare a variable of type typeof(some_expression).
This would be useful, if some_expression is complicated.
E.g., with typeof we could write:
typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
With declare:
declare x = a*b+c*d+e/f;
It should be as 'easy' to implement as typeof, since
declare x = some_expression is equivalent (syntactic sugar) with
typeof(some_expression) x = some_expression
/Jaakko
--
--- Jaakko J rvi, jaakko.jarvi@cs.utu.fi
--- Turku Centre for Computer Science (www.tucs.fi)
--- Lemmink isenkatu 14 A, FIN-20520 Turku, Finland
--- Phone: +358-2-333 8656, Fax: +358-2-333 8600
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/09 Raw View
In article <7ol6hi$ej9$2@news.BelWue.DE>, Dietmar Kuehl
<kuehl@horn.fmi.uni-konstanz.de> writes
>I'm also willing to push this issue forward
>(potentially trying to get the German body into a position of rejecting
>the next version of the Standard, that is after 2003, if this feature
>is not in). But I don't have the necessary insight into the core
>language to write the corresponding proposal... Maybe there is already
>a proposal which was just received to late? Whas it voted on?
Likewise, if you can convince me that it is worthwhile, together with
the kind of material Dietmar suggested I would try to persuade the UK
C++ Panel (equivalent of J16) to support it. But you must put in the
work so that people like myself and Dietmar can argue for it.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/09 Raw View
In article <37AE541B.A998F729@cs.utu.fi>, Jaakko J rvi
<jaakko.jarvi@cs.utu.fi> writes
>The semantics is to declare a variable of type typeof(some_expression).
>
>This would be useful, if some_expression is complicated.
>
>E.g., with typeof we could write:
>
> typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
>
>With declare:
>
> declare x = a*b+c*d+e/f;
>
>It should be as 'easy' to implement as typeof, since
>
>declare x = some_expression is equivalent (syntactic sugar) with
>typeof(some_expression) x = some_expression
with typeof you do not need declare, however declare would not provide
all the utility of typeof, and is less clear in intent.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/10 Raw View
Francis Glassborow <francis@robinton.demon.co.uk> writes:
> Likewise, if you can convince me that it is worthwhile, together with
> the kind of material Dietmar suggested I would try to persuade the UK
> C++ Panel (equivalent of J16) to support it. But you must put in the
> work so that people like myself and Dietmar can argue for it.
This is not anything like a formal proposal, but perhaps it's a
starting point.
Given
namespace std
{
template<typename T> void __typeof__(volatile const T &);
}
I propose that the type of 'typeof(expr)' be defined to be the same
as the deduced type of T in the call 'std::__typeof__(expr);'. The
expression 'expr' is not evaluated.
This semantics makes typeof of a reference be the same as typeof of
its referrant, and discards top-level const and volatile, somewhat
like the behavior of sizeof.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jaakko =?iso-8859-1?Q?J=E4rvi?= <jaakko.jarvi@cs.utu.fi>
Date: 1999/08/10 Raw View
Francis Glassborow wrote:
>
> with typeof you do not need declare, however declare would not provide
> all the utility of typeof, and is less clear in intent.
I agree, that declare would not provide all the utility of typeof,
but I still think it would be useful (in addition to typeof).
See my example:
> typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
vs.
> declare x = a*b+c*d+e/f;
I find the first line less clear in intent.
If we had typeof, declare could be implemented as a macro (with
different syntax though):
#define DECLARE(VAR,EXPR) typeof(EXPR) VAR = EXPR
Consequently, the implementation should be
more or less straightforward.
/Jaakko
--
--- Jaakko Jdrvi, jaakko.jarvi@cs.utu.fi
--- Turku Centre for Computer Science (www.tucs.fi)
--- Lemminkdisenkatu 14 A, FIN-20520 Turku, Finland
--- Phone: +358-2-333 8656, Fax: +358-2-333 8600
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/11 Raw View
In article <37AFAC37.6B7F4253@cs.utu.fi>,
Jaakko =?iso-8859-1?Q?J=E4rvi?= <jaakko.jarvi@cs.utu.fi> wrote:
> Francis Glassborow wrote:
> >
> > with typeof you do not need declare, however declare would not
provide
> > all the utility of typeof, and is less clear in intent.
>
> I agree, that declare would not provide all the utility of typeof,
> but I still think it would be useful (in addition to typeof).
>
> See my example:
> > typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
> vs.
> > declare x = a*b+c*d+e/f;
> I find the first line less clear in intent.
I don't. Even if I agreed, however, I think the idiom to be poor.
What you are doing is asking the compiler to determine the type of a
complex expression and at the same time declare an instance of that
type. If I can't determine the type at the time I write such a line,
I'd hardly want the compiler to do so for me. There may be rare cases
in which this is useful, but they are too rare to warrant yet another
keyword when the typeof keyword gives the same identical functionality.
> If we had typeof, declare could be implemented as a macro (with
> different syntax though):
>
> #define DECLARE(VAR,EXPR) typeof(EXPR) VAR = EXPR
>
> Consequently, the implementation should be
> more or less straightforward.
Though the use of macros should be avoided, especially by the standard
libraries, the fact that you just provided one should be proof enough
that we have no need for another keyword. (Yes, I'm aware that the
macro you provided is wrought full of potential bugs where EXPR is
evaluated twice.)
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/11 Raw View
Jaakko J=E4rvi <jaakko.jarvi@cs.utu.fi> writes:
> If we had typeof, declare could be implemented as a macro (with
> different syntax though):
> #define DECLARE(VAR,EXPR) typeof(EXPR) VAR =3D EXPR
> Consequently, the implementation should be=20
> more or less straightforward.
The C++ committee has adopted an Occam's Razor approach, which dictates
that redundant facilities already implementable within the language will
not be added. Given that declare is easily implementable given typeof,
while typeof is not implementable in terms of declare, there is no chance
that declare would be adopted.
This is a good thing.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/11 Raw View
<niklasb@my-deja.com> wrote in message news:7nt3vl$1oe$1@nnrp1.deja.com...
> I have in mind a keyword, typeof, which would yield the type
> of an expression. Like its cousin "sizeof," typeof would not
> actually evaluate anything at run-time.
I love this idea. I've been arguing with people about it in the Borland C++
language newsgroup. For some reason, there were some people that were down
right hostile to the idea.
Greg Brewer
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/11 Raw View
In article <t7d7ww1vrz.fsf@calumny.jyacc.com>, Hyman Rosen
<hymie@prolifics.com> writes
>This is not anything like a formal proposal, but perhaps it's a
>starting point.
In order to gain support you need to explain carefully (with examples)
exactly what it is to do and what kind of non-academic problem it will
solve. Code examples help.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1999/08/11 Raw View
In article <7opt86$pku$1@nnrp1.deja.com>, sirwillard@my-deja.com wrote:
> > See my example:
> > > typeof(a*b+c*d+e/f) x = a*b+c*d+e/f;
> > vs.
> > > declare x = a*b+c*d+e/f;
> > I find the first line less clear in intent.
>
> I don't. Even if I agreed, however, I think the idiom to be poor.
> What you are doing is asking the compiler to determine the type of a
> complex expression and at the same time declare an instance of that
> type. If I can't determine the type at the time I write such a line,
> I'd hardly want the compiler to do so for me. There may be rare cases
> in which this is useful, but they are too rare to warrant yet another
> keyword when the typeof keyword gives the same identical functionality.
It is all about maintenance, and not forcing the programmer to specify
things that he really doesnt care about. Say I want to exchange variables
x and y. I need a temporary variable tmp. I dont want to specify the size
of tmp, just "big enough".
Anything that I have to specify is one thing that I can get right or
wrong. Anything that I dont have to specify is one thing that I cannot get
wrong. I prefer things that dont go wrong.
> > If we had typeof, declare could be implemented as a macro (with
> > different syntax though):
> >
> > #define DECLARE(VAR,EXPR) typeof(EXPR) VAR = EXPR
> >
> > Consequently, the implementation should be
> > more or less straightforward.
>
> Though the use of macros should be avoided, especially by the standard
> libraries, the fact that you just provided one should be proof enough
> that we have no need for another keyword. (Yes, I'm aware that the
> macro you provided is wrought full of potential bugs where EXPR is
> evaluated twice.)
I am not aware of that. Any reason why typeof() would evaluate its
argument, instead of behaving like sizeof ()? See how simple it is to make
mistakes? That is why I say:
Anything that I have to specify is one thing that I can get right or
wrong. Anything that I dont have to specify is one thing that I cannot get
wrong. I prefer things that dont go wrong.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/11 Raw View
Francis Glassborow <francis@robinton.demon.co.uk> writes:
> In order to gain support you need to explain carefully (with examples)
> exactly what it is to do and what kind of non-academic problem it will
> solve. Code examples help.
The basic problem it addresses is that there is no way, in general,
to obtain the type of an expression as a typename that can be used
in further declarations. This is especially a problem with templates.
Here's one example. The goal is to write a function template with a
type parameter representing a functor. The instantiated function
receives an integer parameter, and returns a vector of objects
obtained by invoking operator() on a the functor. Here's how it looks
with typeof -
using namespace std;
#include <vector>
template < typename Creator >
vector < typeof(Creator()(0)) > make_vector(Creator c, int n)
{
vector < typeof(c(0)) > v;
for (int i = 0; i < n; ++i)
v.push_back(c(i));
return v;
}
int f(int n) { return n * n; }
int main()
{
vector < int > v = make_vector(f, 10);
return v[0];
}
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/11 Raw View
Dietmar Kuehl wrote:
>
> Hi,
> rado42 (rado42@my-deja.com) wrote:
> : I suggest to vote for or against it it.
>
> To what end? The standard was approved last year and will remain stable
> until at least 2003. Of course, we may lobby our favorite compiler
> provider to implement this feature and we might even get several
> providers to implement this feature exactly the same. It is even
> implemented by existing compilers eg. I know that g++ at least had this
> feature for some years. [Dietmar is checking whether the features is
> still there] Cool: gcc still has it.
>
> So, we should demonstrate useful application of this keyword, show
> where things become possible which were not possible before and/or much
> easier to warrent this feature. If we can provide evidence that this
> feature is needed by showing the difference of the code with and
> without this feature, I can imagine that for the next round of
> standardization we can get it in.
[...]
Well, assume we have a mathematical library supporting the following
types:
template<int Precision, int ExpRange> class BigFloat;
template<int Prec1, int Range1, int Prec2, int Range2>
BigFloat<(Prec1<Prec2)? Prec1:Rec2, Range1+Range2>
operator*(BigFloat<Prec1, Range1> const&,
BigFloat<Prec2, Range2> const&)
template<class CoeffType> class Polynom
{
public:
template<class T>
typeof(CoeffType()*T()) operator()(T const& t);
static Polynom x;
// ...
};
template<class T, int m, int n> class Matrix;
template<class T, int n>
Matrix<T, n, n> unitMatrix();
template<class T1, class T2, int l, int m, int n>
Matrix<typeof(T1()*T2()), l, n>
operator*(Matrix<T1, l, m> const&,
Matrix<T2, m, n> const&);
template<class T, int n> struct PowerType
{
typedef typeof(typename PowerType<T, n-1>::type()*T()) type;
};
template<class T> struct PowerType<T, 1>
{
typedef T type;
};
template<class T, int n>
typename PowerType<T, n>::type det(Matrix<T, n> const&);
Now an user can do things like the following:
#include "mathtypes.h"
int main()
{
typedef Polynom
Matrix<double, 3, 4> m1;
Matrix<BigFloat<100, 200>, 4, 3> m2;
Polynom<BigFloat<100, 600> P=
det(m1*m2 - Polynom<double>::x*unitMatrix<3>());
// this gived the characteristic polynom of m1*m2
Polynom<Matrix<double, 5, 5> > p1, p2;
// Two polynoms where the coefficients are 5x5 matrices
Matrix<double, 5, 5> m3=(p1*p2)(3.5);
// Calculates the value of the product polynome at the
// (double) value 3.5
Polynom<double> p3;
p1 = p2(p3); // insert polynom p3 into p2, giving another polynom
Matrix<double, 5, 5> m4=p3(m2);
// insert matrix into double polynom
Matrix<Polynom<double>, 3, 4> m5;
// a matrix whose coefficients are polynoms
Matrix<Polynom<double>, 3, 3> m6 = m5*m2;
}
Now try to get the same flexibility with traits. Happy typing! ;-)
And I didn't take into account that you might want to use other
types as matrix coefficients (say Rational from libg++).
With typeof, this works automatically. Whenever there's
a multiplication of types (even if it is implicit through type
conversions), you automatically get the corresponding result
type for multiplications of matrices and polynoms.
With traits classes, you'd have to write tons of additional
traits, for each new type of multiplication which can arise
(i.e. each first type multiplied with each second type).
This includes multiplications which are made possible through
implicit conversions only (say, you have defined multiplication
of double with BigFloat, then you must also define the
multiplication_traits for multiplication of float with BigFloat).
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/12 Raw View
Francis Glassborow <francis@robinton.demon.co.uk> writes:
> In order to gain support you need to explain carefully (with examples)
> exactly what it is to do and what kind of non-academic problem it will
> solve. Code examples help.
If you think about it, there is a fundamental asymmetry in function
template argument deduction, in that the deduced types are fully
available to be used within the function, including declaring new
variables of the deduced types and derivations based on them, but
there is no way to use such a deduced type *outside* the function.
It is this asymmetry which typeof corrects.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/12 Raw View
Hyman Rosen wrote:
> If you think about it, there is a fundamental asymmetry in function
> template argument deduction, in that the deduced types are fully
> available to be used within the function,
This ``asymmetry'' is called scoping, by the way.
I am not sure that scoping has to be ``corrected''.
--
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://reality.sgi.com/austern_mti/std-c++/faq.html ]