Topic: Implicit type declaration proposals ("let"or "auto") status?
Author: "Fernando Cacciola" <fcacciola@gosierra.com>
Date: Fri, 15 Mar 2002 18:00:42 GMT Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20020312090245.54465E@brangdon.madasafish.com...
> fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> > I'd be more than happy with any of these:
> >
> > 1) template syntax:
>
> Indeed. If return type deduction is allowed, it's hard to see why it
> shouldn't be allowed under the template syntax.
>
Agreed. (I put it top of the list intentionally)
>
> > [example function with single-letter variable names and no types]
> > I leave to all of you to judge whether the second example would be a
> > nice piece of code to encounter in a C++ program, in spite the fact
> > that it is actually 100% type safe, and to see that this is
> > exactly where a nameless auto declaration will lead us.
>
> I don't think it is much less readable than:
>
> template<class X,class Y,class Z,class R>
> R foo(X x,Y y, Z z) {
> A a = x + y;
> B b = y - z;
> C c = a * b - y;
>
> if (a > b)
> return c;
> else
> return 0;
> }
>
> I have added type-names, but it doesn't help, because I didn't pick
> meaningful names.
I think it does:
Even with all the lack of expresiveness here, I can tell that the
expressions like 'x + y','y - z', ... involve DIFFERENT TYPES. That's a lot
of information.
Consider these situations:
(A)
Suppose I'm worry about the implicit conversions that I know for sure will
ocurr.
Since I do have type 'names', I can do this:
typedef typeof(X + Y) A ;
A a = static_cast<A>(x) + static_cast<A>(y);
Which you should agree is safer in generic code because the implicit
conversion rules for mixed-type expressions don't always do the right thing.
Furthermore, even you happen to trust you compiler's good judgment of how to
properly evaluate 'x + y', you might want to play really safe and use:
A a = boost::numeric_cast<A>(x) + boost::numeric_cast<A>(y);
which detects out of range conversions.
But you can avoid all these if you know, because of the type 'names', that x
and y are of the same type.
(B)
What if you want to do this:
if ( a > 0 ) ...
and the compiler can't choose the right operator > (gives ambiguity).
Having a type name, I can write
if ( a > static_cast<A>(0) ) ...
(C)
I can use the type name 'R', regardless of what it really is, to select a
template class instance.
template<class X,class Y,class Z,class R>
R foo(X x,Y y, Z z)
{
A a = x + y;
B b = y - z;
C c = a * b - y;
if (a > b)
{
return some<R>::foo(c);
}
else
return 0;
}
IOW, type 'names' are so powerful and fundamental that there are a lot of
things they are useful for even if they are meaningless.
--
Fernando Cacciola
Sierra s.r.l.
fcacciola@gosierra.com
www.gosierra.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Fernando Cacciola" <fcacciola@gosierra.com>
Date: Fri, 15 Mar 2002 19:33:22 GMT Raw View
"Anders J. Munch" <andersjm@dancontrol.dk> wrote in message
news:3c8c7a54$0$63798$edfadb0f@dspool01.news.tele.dk...
> "Fernando Cacciola" <fcacciola@gosierra.com> wrote in message
> news:a6atjr$d0g48$1@ID-44132.news.dfncis.de...
> > I did mentioned a real problem when we discussed this on the boost list:
> >
> > Auto-deduced return types will ALWAYS involve an IMPLICIT conversion
> unless
> > all return expression have the same type.
> >
> > The problem is that the *lack of a name* for the auto-deduced return
type
> > prevents the programmer to use an *explicit* conversion even if he/she
> > intended to.
>
> unknown type + explicit conversion = disaster
>
> Explicit conversions are unsafe conversions.
??? Could you elaborate this statement?
> Using explicit
> conversions on something of template parameter type or of auto-deduced
> type is asking for trouble.
>
Why?
> If you can show an example where an explicit conversion on an unknown
> type is desirable, then please do, and we can discuss that.
Example 1:
template<class U>
struct arithmetic_kernel
{
template<class T>
static T add ( T x, T y )
U xu = cvt_number<U>(x);
U yu = cvt_number<U>(y);
U ru = xu + yu ;
T r = cvt_number<T>(ru);
return r ;
}
} ;
int main()
{
typedef arithmetic_kernel<long long> LL_Kernel ;
try
{
int a = std::numeric_limits<int>::max();
int b = 1 ;
int c = LL_Kernel::add(a,b); // this overflow is detected by
cvt_number<>
}
catch ( cvt_number_overflow ) {}
return 0 ;
}
The above is a very simplifed version of a real framework which basically
provides operational kernels that allows operations to be carried out with a
user supplied inner type which can increase accuaracy/errror handling.
In this example, cvt_number<> is a custom numeric cast which is capable of
detecting range violations (throwing in that case) and which can be
overloaded for UDTs.
If the kernel used implicit casting, as if it were
template<class T>
static T add ( T x, T y )
U xu = x;
U yu = y;
U ru = xu + yu ;
T r = ru;
return r ;
}
its usefulness would be lowered considerabily by the fact that the user
wouldn't be allowed to customize the conversion behaviour.
Example 2:
template<class GCoord> point
{
GCoord x,y ;
point( GCoord ax, GCoord ay ) : x(ax), y(ay) {}
} ;
template<class GScalar,class GPoint>
GScalar Distance ( GPoint const& p0, GPoint const& p1 )
{
return sqrt ( pow2 ( static_cast<GScalar>(p1.x - p0.x) ) + pow2 ( static_cast<GScalar>(p1.y - p0.y) ) ) ;
}
int main()
{
point<int> a(0,0);
point<int> b(1,1);
double len0 = Distance<double>(a,b); // sqrt(2.0) (~1.41)
double len1 = Distance<int>(a,b) ; // sqrt(2) == 1
return 0 ;
}
In this second example, the Distance function is enhanced w.r.t to the straightforward implementation in that allows you to specific the 'scalar' type correspoding to the space.
A geometric system can use integer-coordinate points, but it doesn't mean that scalars (ie. scale factors, distances, etc..) should also be integers, in fact that would render the system pretty useless in some applications.
Here again, a explicit cast is used so that the appropriate 'pow2' and 'sqrt' overloads are picked.
(BTW: actually, on a comformant system, the second call (with <int>) won't compile since sqrt(int) is ambiguous in C++)
The bottom line is that a template parameter type is NOT an unknown type, it is one of a set of types which meet specific requierments. There is nothing wrong in explicitely casting to a template type (or auto deduced type) in a well designed generic algorithm (that is, one in which T,U,X,Y... represent well defined "concepts" and not arbitrary types).
>
> > I suggested that whatever the syntax, auto declarations should require a
> > name (or at the very least, allow a name to be specified)
> > Although in the case of auto variable declarations, the name can be
> obtai
ned
> > using typeof(), in the case of auto return types there is no way to
obtain
> a
> > name for the deduced return type unless such a name is required or
allowed
> > to be provided.
>
> For most cases you can use
> typeof(return-expression)
>
I see.
> This won't work if the return expression itself somehow depends on the
> return type, but then are you really gonna ask the compiler to sort
> out that kind of recursive definition?
>
No, you're right, in those cases I won't be asking for return type deduction
anyway.
> > I can accept that everyone regarded this as a trivial and non-important
> > problem, but I wouldn't like to see that it is just overlooked.
>
> Fair enough. IMHO: Non-important problem.
>
I see.
--
Fernando Cacciola
Sierra s.r.l.
fcacciola@gosierra.com
www.gosierra.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sun, 17 Mar 2002 16:26:22 GMT Raw View
fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> Even with all the lack of expresiveness here, I can tell that the
> expressions like 'x + y','y - z', ... involve DIFFERENT TYPES. That's a
> lot of information.
Surely you mean potentially different types? Type parameters like X and Y
could be deduced to be the same type, and names like A and B could be
typedef'd to be the same.
The same is true of the "auto" version. Each use of "auto" produces a
potentially different type. Introducing meaningless names only adds
information if we use the same name for two things (when it tells us they
are the same).
> IOW, type 'names' are so powerful and fundamental that there are a lot
> of things they are useful for even if they are meaningless.
If you want the type names, by all means put them in. I agree there are
situations where "auto" would be inappropriate.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Fernando Cacciola" <fcacciola@gosierra.com>
Date: Mon, 11 Mar 2002 19:44:11 GMT Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20020308231753.51637G@brangdon.madasafish.com...
> fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> > Although in the case of auto variable declarations, the name can be
> > obtained using typeof(), in the case of auto return types there
> > is no way to obtain a name for the deduced return type unless such
> > a name is required or allowed to be provided.
>
> What is wrong with:
>
> auto f( auto a ) {
> typedef typeof( a ) T;
> typedef typeof( f(a) ) R;
> // ...
> }
>
>
Well, if typeof( f(a) ) can always be "evaluated", considering that is
inside 'itself', then nothing is *wrong*.
I said that there is no way to give a name to the auto-deduced return type
because I didn't though that "typeof( func(arg_list) )" would always work
inside the body of the function whose return type is being deduced; but if
this is possbile, then I agree that it is also *possible* to give a name to
the auto-deduced return type.
Still, I think that this is the wrong way to deal with it, because the
'auto' declaration is already performing all the type deduction, so I would
think that the additional (exact duplicate) deduction is too much just to
give the previous one a name.
I'd be more than happy with any of these:
1) template syntax:
template <typename T, typename R>
R f( T a )
{
return a ; // 'a' of type 'T' is converted to type R
}
2) 'auto' syntax with type name *required*
auto R f ( auto T a )
{
return a ; // 'a' of type 'T' is converted to type R
}
3) 'auto' syntax with type name *optional*
auto typename R ( auto a )
{
return a ; // 'a' of some 'unnamed' autodeduced, and it is converted to
type R
}
I find a syntax that requires/allows a type "name" to be given right in the
declaration much more appealing, though I could live with anything that
allows me to produce that name by hand (such as typeof()), provided that
later can be used in ANY context where a type has been auto deduced.
BTW, perhaps I should try again to explain why is it that I'm so concern
about giving auto-deduced types a 'name': because otherwise implicit
conversions to unknown types would ocurr.
I noticed before in the boost list that a nameless 'auto' declaration will
have a similar effect in code as if unnamed template parameters would be
allowed:
That is, this code:
auto foo( auto x, auto y, auto z)
{
auto a = x + y ;
auto b = y - z ;
auto c = a * b - y ;
if ( a > b )
return c ;
else return 0 ;
}
is actually pretty much the same as this hypothetical-code (which isn't
valid right now)
template<class,class,class,class>
foo(x,y,z)
{
a = x + y ;
b = y - z ;
c = a * b - y ;
if ( a > b )
return c ;
else return 0 ;
}
Because the word 'auto' in the first example conveys *nothing*, so it could
well be avoided all together, leading to the second case.
I leave to all of you to judge whether the second example would be a nice
piece of code to encounter in a C++ program, in spite the fact that it is
actually 100% type safe, and to see that this is exactly where a nameless
auto declaration will lead us.
--
Fernando Cacciola
Sierra s.r.l.
fcacciola@gosierra.com
www.gosierra.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Anders J. Munch" <andersjm@dancontrol.dk>
Date: Tue, 12 Mar 2002 19:05:43 GMT Raw View
"Fernando Cacciola" <fcacciola@gosierra.com> wrote in message
news:a6atjr$d0g48$1@ID-44132.news.dfncis.de...
> I did mentioned a real problem when we discussed this on the boost list:
>
> Auto-deduced return types will ALWAYS involve an IMPLICIT conversion
unless
> all return expression have the same type.
>
> The problem is that the *lack of a name* for the auto-deduced return type
> prevents the programmer to use an *explicit* conversion even if he/she
> intended to.
unknown type + explicit conversion = disaster
Explicit conversions are unsafe conversions. Using explicit
conversions on something of template parameter type or of auto-deduced
type is asking for trouble.
If you can show an example where an explicit conversion on an unknown
type is desirable, then please do, and we can discuss that.
> I suggested that whatever the syntax, auto declarations should require a
> name (or at the very least, allow a name to be specified)
> Although in the case of auto variable declarations, the name can be
obtained
> using typeof(), in the case of auto return types there is no way to obtain
a
> name for the deduced return type unless such a name is required or allowed
> to be provided.
For most cases you can use
typeof(return-expression)
This won't work if the return expression itself somehow depends on the
return type, but then are you really gonna ask the compiler to sort
out that kind of recursive definition?
> I can accept that everyone regarded this as a trivial and non-important
> problem, but I wouldn't like to see that it is just overlooked.
Fair enough. IMHO: Non-important problem.
--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 12 Mar 2002 19:07:07 GMT Raw View
andersjm@dancontrol.dk (Anders J. Munch) wrote (abridged):
> Infinite recursion in the type-checker. The return type of f<U> may
> depend on R which depends the return type of f<U>.
That can happen even if the type is named in the template list.
template <typename R, typename T>
R func( T t ) {
return R(t);
}
This kind of thing is a real concern, but its mostly orthogonal to the
question of whether anonymous types are allowed. If anything, using "auto"
to make the deduced type anonymous will reduce the chances of getting an
infinite recurse in the type checker.
As I understand it, even without return type deduction, type-checking
template code can be equivalent to solving the Halting Problem, ie
impossible in general. This is because templates provide a fully Turing
complete compile-time language. It includes looping (via recursion) and
conditionals (via partial specialisation). You can write arbitrarily
complex type-expressions. Return type deduction doesn't make the situation
so very much worse.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 12 Mar 2002 19:07:25 GMT Raw View
fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> I'd be more than happy with any of these:
>
> 1) template syntax:
Indeed. If return type deduction is allowed, it's hard to see why it
shouldn't be allowed under the template syntax.
> [example function with single-letter variable names and no types]
> I leave to all of you to judge whether the second example would be a
> nice piece of code to encounter in a C++ program, in spite the fact
> that it is actually 100% type safe, and to see that this is
> exactly where a nameless auto declaration will lead us.
I don't think it is much less readable than:
template<class X,class Y,class Z,class R>
R foo(X x,Y y, Z z) {
A a = x + y;
B b = y - z;
C c = a * b - y;
if (a > b)
return c;
else
return 0;
}
I have added type-names, but it doesn't help, because I didn't pick
meaningful names.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Fernando Cacciola" <fcacciola@gosierra.com>
Date: Fri, 8 Mar 2002 19:09:10 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message
news:a6akov$jnc$1@bob.news.rcn.net...
> This example is silly. (I really hope) nobody ever suggested that the
return
> type should be dependent on the runtime values: that would require a
> completely new abstract machine model.
>
> [SNIPPED]
>
> I am more than happy to discuss real problems, if there are any,
> but let's try to view the proposed feature in terms of its actual
advantages
> and drawbacks, and in particular let's let the language implementors who
are
> listening tell us if it's hard to implement.
>
> -Dave
>
I did mentioned a real problem when we discussed this on the boost list:
Auto-deduced return types will ALWAYS involve an IMPLICIT conversion unless
all return expression have the same type.
The problem is that the *lack of a name* for the auto-deduced return type
prevents the programmer to use an *explicit* conversion even if he/she
intended to.
I suggested that whatever the syntax, auto declarations should require a
name (or at the very least, allow a name to be specified)
Although in the case of auto variable declarations, the name can be obtained
using typeof(), in the case of auto return types there is no way to obtain a
name for the deduced return type unless such a name is required or allowed
to be provided.
I can accept that everyone regarded this as a trivial and non-important
problem, but I wouldn't like to see that it is just overlooked.
--
Fernando Cacciola
Sierra s.r.l.
fcacciola@gosierra.com
www.gosierra.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 9 Mar 2002 05:45:18 GMT Raw View
fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> Although in the case of auto variable declarations, the name can be
> obtained using typeof(), in the case of auto return types there
> is no way to obtain a name for the deduced return type unless such
> a name is required or allowed to be provided.
What is wrong with:
auto f( auto a ) {
typedef typeof( a ) T;
typedef typeof( f(a) ) R;
// ...
}
Typeof() can be used on functions. The above "unnamed type" version would
be roughly equivalent to the "named type" version:
template <typename T, typename R>
R f( T a ) {
// ...
}
In both cases R can be used for conversions.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Craig Tiller <ctiller@bigpond.net.au>
Date: Sun, 10 Mar 2002 15:42:35 GMT Raw View
>
>That doesn't follow. We can design deduction rules which assign a type at
>compile-time. Here are some examples, of increasing lassitude and
>complexity.
>
>(1) There may only be one return statement.
>
>(2) All return statements must have identical type.
>
>(3) The types of return statements are combined pair-wise, in the order
>they appear in the source code, as if they were arguments to the ?:
>conditional operator.
>
>Basically, the language already assigns a static type to the expression
>
> rand() ? 10 : 10.0;
>
>so we can also assign one to:
>
> template <typename T>
> T func() {
> if (rand())
> return 10;
> else
> return 10.0;
> }
>
>There are strong arguments against adding deduction of return types to the
>language, but this isn't one of them.
Everything seems to make so much more sense after seeing that :)It's all good
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Anders J. Munch" <andersjm@dancontrol.dk>
Date: Mon, 11 Mar 2002 17:36:35 GMT Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20020308231753.51637G@brangdon.madasafish.com...
> fcacciola@gosierra.com (Fernando Cacciola) wrote (abridged):
> > Although in the case of auto variable declarations, the name can be
> > obtained using typeof(), in the case of auto return types there
> > is no way to obtain a name for the deduced return type unless such
> > a name is required or allowed to be provided.
>
> What is wrong with:
>
> auto f( auto a ) {
> typedef typeof( a ) T;
> typedef typeof( f(a) ) R;
> // ...
> }
Infinite recursion in the type-checker. The return type of f<U> may
depend on R which depends the return type of f<U>.
--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Craig Tiller" <craig@clinicdesign.com.au>
Date: Fri, 8 Mar 2002 09:26:19 GMT Raw View
Which is exactly why we shouldn't allow automatic deduction of return values
of functions
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20020228225533.55813G@brangdon.madasafish.com...
> ctiller@bigpond.net.au (Craig Tiller) wrote (abridged):
> > My *big* concern though is on how many code paths this is going to
> > generate... consider (contrived to be brief):
> >
> > class A
> > {
> > public:
> > bool next_val() { return rand()%7 == 0; }
> > };
> >
> > class B
> > {
> > public:
> > bool next_val() { return rand()%28391 == 0; }
> > };
> >
> > std::auto example_func( bool f )
> > {
> > if (f)
> > return A();
> > else
> > return B();
> > }
>
> I don't see how a return type can be deduced for example_func(), because
> it has multiple returns with incompatible types. Type-deduction must be
> independent of the runtime values.
>
> Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
> brangdon@cix.co.uk | And close your eyes with holy dread,
> | For he on honey dew hath fed
> http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 8 Mar 2002 16:37:25 GMT Raw View
craig@clinicdesign.com.au (Craig Tiller) wrote (abridged):
> > I don't see how a return type can be deduced for example_func(),
> > because it has multiple returns with incompatible types.
> > Type-deduction must be independent of the runtime values.
>
> Which is exactly why we shouldn't allow automatic deduction of return
> values of functions
That doesn't follow. We can design deduction rules which assign a type at
compile-time. Here are some examples, of increasing lassitude and
complexity.
(1) There may only be one return statement.
(2) All return statements must have identical type.
(3) The types of return statements are combined pair-wise, in the order
they appear in the source code, as if they were arguments to the ?:
conditional operator.
Basically, the language already assigns a static type to the expression
rand() ? 10 : 10.0;
so we can also assign one to:
template <typename T>
T func() {
if (rand())
return 10;
else
return 10.0;
}
There are strong arguments against adding deduction of return types to the
language, but this isn't one of them.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Fri, 8 Mar 2002 17:26:03 GMT Raw View
This example is silly. (I really hope) nobody ever suggested that the return
type should be dependent on the runtime values: that would require a
completely new abstract machine model.
I'm not sure if it gives exactly the results we'd all like, but the deduced
return type could be specified to be the same as the type of
true ? (r1) : true ? (r2) : true ? (r3) ... : true ? (rN);
where r1...rN are the N expressions which are returned in the function. It's
no more complicated than what the compiler must already do to handle "return
a?b:c;" AFAICT.
Also, where are the "generated code paths" here? I think there's an
extraordinary amount of FUD swirling around the deduced return type
proposal. I am more than happy to discuss real problems, if there are any,
but let's try to view the proposed feature in terms of its actual advantages
and drawbacks, and in particular let's let the language implementors who are
listening tell us if it's hard to implement.
-Dave
"Craig Tiller" <craig@clinicdesign.com.au> wrote in message
news:3c87eca5@duster.adelaide.on.net...
> Which is exactly why we shouldn't allow automatic deduction of return
values
> of functions
>
> "Dave Harris" <brangdon@cix.co.uk> wrote in message
> news:memo.20020228225533.55813G@brangdon.madasafish.com...
> > ctiller@bigpond.net.au (Craig Tiller) wrote (abridged):
> > > My *big* concern though is on how many code paths this is going to
> > > generate... consider (contrived to be brief):
> > >
> > > class A
> > > {
> > > public:
> > > bool next_val() { return rand()%7 == 0; }
> > > };
> > >
> > > class B
> > > {
> > > public:
> > > bool next_val() { return rand()%28391 == 0; }
> > > };
> > >
> > > std::auto example_func( bool f )
> > > {
> > > if (f)
> > > return A();
> > > else
> > > return B();
> > > }
> >
> > I don't see how a return type can be deduced for example_func(), because
> > it has multiple returns with incompatible types. Type-deduction must be
> > independent of the runtime values.
> >
> > Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
> > brangdon@cix.co.uk | And close your eyes with holy dread,
> > | For he on honey dew hath fed
> > http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
> >
> > ---
> > [ comp.std.c++ is moderated. To submit articles, try just posting
with ]
> > [ your news-reader. If that fails, use
lto:std-c++@ncar.ucar.edu ]
> > [ --- Please see the FAQ before
]
> > [ FAQ:
arch.att.com/~austern/csc/faq.html ]
> >
>
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: comeau@panix.com (Greg Comeau)
Date: Fri, 1 Mar 2002 15:51:27 GMT Raw View
In article <memo.20020228225525.55813D@brangdon.madasafish.com>,
Dave Harris <brangdon@cix.co.uk> wrote:
>cjnygard@fast.net (Carl Nygard) wrote (abridged):
>> >> template <typename X, typename Y, typename R> R max( X x, Y y ) {
>> >> return x < y ? y : x;
>> >> }
>> >>
>> >> long r = max( 99, 42L ); // OK! R deduced to long.
>>
>> How? 99 < 42, whether they are ints or longs or whatever, so R is int,
>> which is cast (coerced) to long.
>
>The type R is bound to the type of the return expression
What? The above call to max is an error.
--
Greg Comeau GA BETA:4+ New Windows Backends PLUS 'export' beta#2 online!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried 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://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 2 Mar 2002 19:27:03 GMT Raw View
comeau@panix.com (Greg Comeau) wrote (abridged):
> > The type R is bound to the type of the return expression
>
> What? The above call to max is an error.
It's an error according to the current standard, but we are discussing
possible extensions. If you realise that and mean it is an error even with
the template return type deduction extension, please explain why.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Thu, 21 Feb 2002 16:05:14 GMT Raw View
Dave Harris wrote:
>
> igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
>
> > Choosing between one tool and another tool more flexible/powerfull
> > I'll choose the latter.
>
> I have been arguing against having to make that choice. I want both auto
> and typeof. Typeof for power, auto for simplicity. Typeof for experts,
> auto for novices.
I was talking about keyworded auto vs. template-like variable
definitions (and thus #defined auto). If you meant the choice between
auto and typeof then I'm not making this choice either. I'm after having
them both. They are hardly interchangeable and each may serve its own
purpose. You've agreed that template-like declarations are more flexible
then plain 'auto', and it seems a shame to throw them away for the sake
of simplicity.
> Or perhaps we disagree about macros. Are you suggesting that #define Auto
> be added to the standard library, so that we have to #include <Auto>
> before we can use it? I think this will lead to the same kind of problems
> we already see with NULL. People will forget to #include it, and their
> code will still compile because they do #include <vector> and vector uses
> Auto. And then their code will break when they go to a different vendor
> whose vector does not use Auto.
>
> Even if they do remember to include it, we have condemned every C++ file
> in the world, for ever more, to start with #include <Auto>. Either that or
> risk Auto not being available when we want to use it. The complexity is
> hardly worth it for the simple cases which Auto is intended to help.
>
> If the Auto is not even standard, the problems get worse. We will get
> myriad different spellings of it and its header. It is a bit like
> #define BEGIN {, where people invent their own incompatible little
> languages. Auto will belong to C++ dialects.
Frankly I did not consider this mess. You have almost persuaded me
that #defined auto will cause severe problems unlike keyworded one. I'm
just feeling uneasy about creating a keyword for something that can be
achieved other way around.
Another thing is that 'auto' doesn't cover all cases one might want.
Sometimes you need your local variable to be a reference or a const
reference to its initializer. Should we introduce auto_ref and
auto_constref keywords then? (At first glance they might be confused
with auto_ptr).
A better solution is to make 'auto' behave like a deduced type
parameter (see my other post). Then one may use it:
auto x = 5; // x is int
const auto& y = "abc"; // y is const char (&)[4]
auto& z = x; // z is int&
Could we agree on such functionality of 'auto' keyword? This way
'auto' is looking like a special type name, which is resolved at compile
time. However unlike other types it cannot be used in function
arguments, function return type, class data members... That's why I was
advocating template-like syntax: it's consistent and it can be used
everywhere:
template <typename __t >
__t x = 5L;
template <typename __t >
void foo(__t x);
The meaning of these notations is clear: the type of x is deduced
from the type of the expression used to initialize it. Template type
parameters used as function return types are not deduced. So are
template parameters of a class template. You see, if you (not personal
You, I use just a general 'you' in the post) if you treat 'auto' as
template-like deduced type, it's clear where it can be used and where it
can not be. Making 'auto' look like a type without actually being one is
more confusing, IMHO.
Having said this, it looks like all three features (keyword 'auto',
operator 'typeof' and template syntax for local variables) are worth
putting into the language.
> Macros don't respect namespaces, so making Auto a macro, whether de facto
> standard or actual standard, has hardly any advantage over making it a
> proper keyword.
Right. And 'auto' (whichever way it is implemented) should not be
restricted or scoped to some namespace.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Thu, 21 Feb 2002 20:46:47 GMT Raw View
I would argue for adding "let", rather than giving
"auto" an additional meaning. "auto" is already an
attribute in declarations, which makes this
additional use confusing.
Think of it this way. Write up "let" as you would
for an introductory programming text. Now write up
this new use of "auto". Which has the shorter,
clearer description?
The main use for this is not to allow the creation
of new, ever more obscure template gimmicks. It's
to make the use of STL iterators easier than the use
of subscripts.
vector<float> tab;
....
for (let p = tab.begin(); p != tab.end(); p++)
{ ... }
John Nagle
Animats
Igor A. Goussarov wrote:
> Dave Harris wrote:
>
>>igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
>>
>>
>>>Choosing between one tool and another tool more flexible/powerfull
>>>I'll choose the latter.
>>>
>>I have been arguing against having to make that choice. I want both auto
>>and typeof. Typeof for power, auto for simplicity. Typeof for experts,
>>auto for novices.
>>
>
> I was talking about keyworded auto vs. template-like variable
> definitions (and thus #defined auto). If you meant the choice between
> auto and typeof then I'm not making this choice either. I'm after having
> them both. They are hardly interchangeable and each may serve its own
> purpose. You've agreed that template-like declarations are more flexible
> then plain 'auto', and it seems a shame to throw them away for the sake
> of simplicity.
>
>
>>Or perhaps we disagree about macros. Are you suggesting that #define Auto
>>be added to the standard library, so that we have to #include <Auto>
>>before we can use it? I think this will lead to the same kind of problems
>>we already see with NULL. People will forget to #include it, and their
>>code will still compile because they do #include <vector> and vector uses
>>Auto. And then their code will break when they go to a different vendor
>>whose vector does not use Auto.
>>
>>Even if they do remember to include it, we have condemned every C++ file
>>in the world, for ever more, to start with #include <Auto>. Either that or
>>risk Auto not being available when we want to use it. The complexity is
>>hardly worth it for the simple cases which Auto is intended to help.
>>
>>If the Auto is not even standard, the problems get worse. We will get
>>myriad different spellings of it and its header. It is a bit like
>>#define BEGIN {, where people invent their own incompatible little
>>languages. Auto will belong to C++ dialects.
>>
>
> Frankly I did not consider this mess. You have almost persuaded me
> that #defined auto will cause severe problems unlike keyworded one. I'm
> just feeling uneasy about creating a keyword for something that can be
> achieved other way around.
> Another thing is that 'auto' doesn't cover all cases one might want.
> Sometimes you need your local variable to be a reference or a const
> reference to its initializer. Should we introduce auto_ref and
> auto_constref keywords then? (At first glance they might be confused
> with auto_ptr).
> A better solution is to make 'auto' behave like a deduced type
> parameter (see my other post). Then one may use it:
>
> auto x = 5; // x is int
> const auto& y = "abc"; // y is const char (&)[4]
> auto& z = x; // z is int&
>
> Could we agree on such functionality of 'auto' keyword? This way
> 'auto' is looking like a special type name, which is resolved at compile
> time. However unlike other types it cannot be used in function
> arguments, function return type, class data members... That's why I was
> advocating template-like syntax: it's consistent and it can be used
> everywhere:
>
> template <typename __t >
> __t x = 5L;
>
> template <typename __t >
> void foo(__t x);
>
> The meaning of these notations is clear: the type of x is deduced
> from the type of the expression used to initialize it. Template type
> parameters used as function return types are not deduced. So are
> template parameters of a class template. You see, if you (not personal
> You, I use just a general 'you' in the post) if you treat 'auto' as
> template-like deduced type, it's clear where it can be used and where it
> can not be. Making 'auto' look like a type without actually being one is
> more confusing, IMHO.
> Having said this, it looks like all three features (keyword 'auto',
> operator 'typeof' and template syntax for local variables) are worth
> putting into the language.
>
>
>>Macros don't respect namespaces, so making Auto a macro, whether de facto
>>standard or actual standard, has hardly any advantage over making it a
>>proper keyword.
>>
>
> Right. And 'auto' (whichever way it is implemented) should not be
> restricted or scoped to some namespace.
>
> Igor
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 21 Feb 2002 16:12:29 CST Raw View
david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> export? explicit instantiation?
> You need to be able to deduce the return type without seeing the
> function body.
With export, the compiler can insist on seeing the function body before
the implicit instantiation. I guess these changes would mean that all
compilers would so insist, where-as nowadays they may hope to avoid doing
so. So it's a step backwards. (Then again, export is but a myth...)
With explicit instantiation, perhaps the return type could be another
explicit parameter.
template <typename X, typename Y>
auto max( X x, Y y );
template max<int, long, long>;
In other words, as if the "auto" simply introduced an implicit template
parameter. In fact, if we allowed template deduction from return types
where the function body is visible:
template <typename X, typename Y, typename R>
R max( X x, Y y ) {
return x < y ? y : x;
}
long r = max( 99, 42L ); // OK! R deduced to long.
then this form of "auto" becomes redundant.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 21 Feb 2002 16:12:48 CST Raw View
igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
> > Typeof for power, auto for simplicity.
>
> You've agreed that template-like declarations are more flexible
> then plain 'auto', and it seems a shame to throw them away for the sake
> of simplicity.
We have 3 proposals: auto, template-like declarations and typeof. What I
am unclear about is the relationship between the template-like
declarations, and typeof. Both are powerful tools. Can either do things
the other cannot? Do we need both?
I had thought not. Either typeof can do the job of template-like
declarations, in which case we don't need them, or else vice versa. I
don't mind which we have. In my previous message I used "typeof" as
short-hand for both proposals. I should have written:
typeof/template-like declarations for power, auto for simplicity.
> auto x = 5; // x is int
> const auto& y = "abc"; // y is const char (&)[4]
> auto& z = x; // z is int&
>
> Could we agree on such functionality of 'auto' keyword?
Looks good to me.
> However unlike other types it cannot be used in function arguments,
> function return type, class data members... That's why I was advocating
> template-like syntax: it's consistent and it can be used everywhere:
Hmmm. Is there any reason auto cannot be used for function arguments? Eg
void print( ostream &os, auto const &x ) {
os << x << "\n";
}
would be syntactic sugar for:
template <typename X>
void print( ostream &os, X const &x ) {
os << x << "\n";
}
The auto form is more pleasant, less cluttered. In order to be truly
worthwhile, we do need some means for deducing return types.
auto max( auto x, auto y ) {
return x < y ? y : x;
}
Here "auto" refers to 3 different types, and the return type cannot be
deduced without seeing the function body. Still, where the function body
is available auto returns could be supported. That would be inline
functions and templates.
These uses of "auto" make it more worthwhile (and cannot be faked with the
template syntax and macros). They also make it a bigger change to the
language, and increase the redundancy with templates. To a degree, this
creeping featurism is turning me off the idea.
> Template type parameters used as function return types are not
> deduced.
True, but that is a rather arbitrary restriction. Why shouldn't:
template <typename X, typename Y, typename R>
R max( X x, Y y ) {
return x < y ? y : x;
}
allow R to be deduced as the type of the return expression? This would
remove one role of typeof. I believe the current "typeof" proposal is that
such templates be written like:
template <typename X, typename Y>
typeof(X() < Y() ? Y() : X()) max( X x, Y y ) {
return x < y ? y : x;
}
The supposed advantage is that the return type can be deduced without
looking at the function body. In practice it seems to put much of the
function body *into* the declaration. The redundancy, the repeating of
expressions, is something I don't like about typeof.
> Making 'auto' look like a type without actually being one is
> more confusing, IMHO.
Well, I think it merely continues the arbitrary rules which already govern
templates. It does not give a name to its type, so the type cannot be
reused, but I don't find that confusing.
> You have almost persuaded me that #defined auto will cause
> severe problems unlike keyworded one.
Excellent. Unfortunately I am now coming to think that auto as a keyword
would be too redundant :-(
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Fri, 22 Feb 2002 06:26:59 GMT Raw View
John Nagle wrote:
>
> I would argue for adding "let", rather than giving
> "auto" an additional meaning. "auto" is already an
> attribute in declarations, which makes this
> additional use confusing.
No, it doesn't. Essentially nobody uses 'auto' in real code, because
it's never necessary. However, because it's a keyword, you're guaranteed
that nobody is using it as a user-defined identifier in any conflicting
context. That's something that you very definitely cannot say about
'let'.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Fri, 22 Feb 2002 22:58:52 GMT Raw View
"Igor A. Goussarov" <igusarov@akella.com> wrote:
> Emily Winch wrote:
> >
> > The compiler _knows_ what the return type is. It works it out. Only the
user
> > needs to be unaware of the return type. All the user needs to know is
> > the constraints on that return type: which are documented by the author
> > just the same as constraints on return values.
>
> The _user_ would be unaware of function return type: declarations
> like "auto x = YourClass<int>::foo<double>(5);" effectively hides the
> type of initializer expression from the user (And this is a good place
> to use 'auto').
> This is the _author_ of the aforementioned function who must be aware of
> the return type. And enforcing this return type in the code is IMHO
> better then documenting it in a separate file.
Definitely. As far as I can see, this falls into the same realm as enforcing
constraints on the return value. The language has no neat place to put
those, which is a shame, but the author of a function is still able to
assert in the function that the constraints hold.
> > > A function may have several return statements. Probably with
> > >expressions of different types (e.g. it return either a pointer to
> > >object or NULL). This would be a challenge for a compiler to guess the
> > >correct return type. More important, it would be a challenge for the
> >
> > Yep. At the moment I like the idea that multiple returns must return
> > the same type (exactly) or cause a compiler error. Otherwise, the
> > compiler just has to do the same as with the ? : operator.
>
> Returning exactly the same type will sometimes require an explicit
> cast. This means you have to put that long type not in the function
> declaration, but in a cast expression in the return statement. What's
> the gain then?
None. If "auto" forced multiple returns to return the same type, authors of
functions returning several different types have no reason to use it.
> > What does the explicit return type give us that is worth all this?
> > Why is "auto" any worse than
> > "typedef typename get_foo_return_type<T, I>::type"?
>
> Explicit return type:
> 1. Makes the compilation straightforward (and thus faster and less
> error-prone). No need to guess the return type. Consider
>
> auto f(int x)
> {
> if (x == 0) return 1;
> return f(x - 1) * x;
> }
>
> Here the return type of f() is self-dependent. Can you describe the
> algorithm which will resolve it correctly? What if there is a
> user-defined type Bug which has a constructor Bug(int) and
> Bug::operator*(int)? Should the compiler iterate through all known types
> to find such buggy possibility?
This does sound like a sticky patch :-( It's a sticky patch in typeof, too.
> 2. Catches programming errors if the return expression does not match
> the desired return type.
I think the author just has to write
template<typename T>
auto foo() {
compile_time_assert<is_sane_foo_return_type<typeof(foo<T>())> >();
// ...
}
No, that isn't nice. But the return type calculating functions I'm writing
at the moment (which incidentally serve to catch similar programming errors)
are even less nice.
> 3. Saves you some typing: you've said that you want all return statement
> expressions to be of the same type. The sometimes you'll need an
> explicit cast or an explicit temporary construction (like "return
> (T*)NULL;", "return MyClass(1);" ). This way you'll have to repeat the
> return type as many times nearly as many return statements you have.
In this case you just wouldn't use auto.
> 4. Lets you employ implicit conversion from return expression to the
> return type.
>
> 'auto' as a function return type has a very limited application:
> 1. the function should be defined at the point of declaration.
> 2. it should not be recursive (directly or indirectly)
Yes. But within this limited application it has the potential to be
extremely
useful.
> > >auto x = "abc";
> > >
> > >what should a compiler guess:
> > >
> > >char x[] = "abc";
> > >const char* x = "abc";
> > >const char (&x)[] = "abc"; ?
> >
> > The compiler guesses the actual type of "abc".
>
> I.e. const char[4]? It's not always what I want. And it's plain wrong
> for array initializer because if
>
> int x[5];
> auto y = x;
>
> is treated like "int y[5] = x;" then this line is ill-formed.
If you _don't_ want the actual type, I think you just don't use auto. To me
that looks like a problem with c-style arrays and strings, not a problem
with auto.
> > >const auto& x = "abc";
> > >map<auto, auto>& y = myMap; // here both auto are independent.
> > >
> > >But don't you think that it's getting closer to the template semantics?
> > >If so then using template syntax here is more consistent.
> >
> > Template semantics are used to introduce a type which can be provided
> > by the user of the code. auto semantics would be used to provide a type
> > which is provided by the author of the code. I think conflating the two
> > is confusing.
>
> Sorry, I haven't made myself clear. I meant "it's getting closer to
> the template function type parameter deduction semantics".
To recap, making sure I understood: you are saying (I think) that
template<typename T> const T& x = "abc";
is better than
const auto& x = "abc";
because the former is clearly analogous to
template<typename T>
void foo(const T& x){
}
foo("abc");
What I meant (but didn't say very well) was that adopting this syntax for
auto in this situation would really suggest adopting it for the function
return type situation, and that this
template<typename T> // return type, user shouldn't specify
template<typename U> // template parameter, user should specify
T foo(){
// ...
}
is confusing.
So... what I learned so far:
1. Auto (in whatever form) is not a magic bullet
2. Auto does not play nice with c-style arrays and strings
3. Auto _really_ does not play nice with recursion.
4. It would be necessary yet painful to write asserts to check that the
constraints on the return type of an auto function hold.
and the question: Is it worth all that? I still think so, but I can
definitely
see other people's mileage varying :-)
Emily.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Craig Tiller" <ctiller@bigpond.net.au>
Date: Mon, 25 Feb 2002 11:16:25 GMT Raw View
What if we had templatized typedefs with automatic resolution of typenames,
similar to functions...
namespace std
{
template <class T> typedef T auto;
}
std::auto value = f(); // automatically resolves T from return type of f
Then if we needed a more restricted form, we could do so... (thinking aloud
now)
template <class T> typedef pair<int,T> IntFirstPair;
template <class T> IntFirstPair<T> func( int i ) { ... }
IntFirstPair value = func(3);
This way, we get the auto semantics, in a user controllable fashion when we
need it - so if we wanted to leave more information about the type in the
function call point, then we can...
Also note that in the second example, we get a much (much) nicer way of
expressing
function return types for complicated examples, which I feel is a much
better method than
trying to get the compiler to deduce it (which just makes me feel all wrong)
"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
news:a55iud$gr$1@reader0.news.uk.quza.net...
>
> "Igor A. Goussarov" <igusarov@akella.com> wrote:
> > Emily Winch wrote:
> > >
> > > The compiler _knows_ what the return type is. It works it out. Only
the
> user
> > > needs to be unaware of the return type. All the user needs to know is
> > > the constraints on that return type: which are documented by the
author
> > > just the same as constraints on return values.
> >
> > The _user_ would be unaware of function return type: declarations
> > like "auto x = YourClass<int>::foo<double>(5);" effectively hides the
> > type of initializer expression from the user (And this is a good place
> > to use 'auto').
> > This is the _author_ of the aforementioned function who must be aware of
> > the return type. And enforcing this return type in the code is IMHO
> > better then documenting it in a separate file.
>
> Definitely. As far as I can see, this falls into the same realm as
enforcing
> constraints on the return value. The language has no neat place to put
> those, which is a shame, but the author of a function is still able to
> assert in the function that the constraints hold.
>
> > > > A function may have several return statements. Probably with
> > > >expressions of different types (e.g. it return either a pointer to
> > > >object or NULL). This would be a challenge for a compiler to guess
the
> > > >correct return type. More important, it would be a challenge for the
> > >
> > > Yep. At the moment I like the idea that multiple returns must return
> > > the same type (exactly) or cause a compiler error. Otherwise, the
> > > compiler just has to do the same as with the ? : operator.
> >
> > Returning exactly the same type will sometimes require an explicit
> > cast. This means you have to put that long type not in the function
> > declaration, but in a cast expression in the return statement. What's
> > the gain then?
>
> None. If "auto" forced multiple returns to return the same type, authors
of
> functions returning several different types have no reason to use it.
>
> > > What does the explicit return type give us that is worth all this?
> > > Why is "auto" any worse than
> > > "typedef typename get_foo_return_type<T, I>::type"?
> >
> > Explicit return type:
> > 1. Makes the compilation straightforward (and thus faster and less
> > error-prone). No need to guess the return type. Consider
> >
> > auto f(int x)
> > {
> > if (x == 0) return 1;
> > return f(x - 1) * x;
> > }
> >
> > Here the return type of f() is self-dependent. Can you describe the
> > algorithm which will resolve it correctly? What if there is a
> > user-defined type Bug which has a constructor Bug(int) and
> > Bug::operator*(int)? Should the compiler iterate through all known types
> > to find such buggy possibility?
>
> This does sound like a sticky patch :-( It's a sticky patch in typeof,
too.
>
> > 2. Catches programming errors if the return expression does not match
> > the desired return type.
>
> I think the author just has to write
>
> template<typename T>
> auto foo() {
> compile_time_assert<is_sane_foo_return_type<typeof(foo<T>())> >();
> // ...
> }
>
> No, that isn't nice. But the return type calculating functions I'm writing
> at the moment (which incidentally serve to catch similar programming
errors)
> are even less nice.
>
> > 3. Saves you some typing: you've said that you want all return statement
> > expressions to be of the same type. The sometimes you'll need an
> > explicit cast or an explicit temporary construction (like "return
> > (T*)NULL;", "return MyClass(1);" ). This way you'll have to repeat the
> > return type as many times nearly as many return statements you have.
>
> In this case you just wouldn't use auto.
>
> > 4. Lets you employ implicit conversion from return expression to the
> > return type.
> >
> > 'auto' as a function return type has a very limited application:
> > 1. the function should be defined at the point of declaration.
> > 2. it should not be recursive (directly or indirectly)
>
> Yes. But within this limited application it has the potential to be
> extremely
> useful.
>
> > > >auto x = "abc";
> > > >
> > > >what should a compiler guess:
> > > >
> > > >char x[] = "abc";
> > > >const char* x = "abc";
> > > >const char (&x)[] = "abc"; ?
> > >
> > > The compiler guesses the actual type of "abc".
> >
> > I.e. const char[4]? It's not always what I want. And it's plain wrong
> > for array initializer because if
> >
> > int x[5];
> > auto y = x;
> >
> > is treated like "int y[5] = x;" then this line is ill-formed.
>
> If you _don't_ want the actual type, I think you just don't use auto. To
me
> that looks like a problem with c-style arrays and strings, not a problem
> with auto.
>
> > > >const auto& x = "abc";
> > > >map<auto, auto>& y = myMap; // here both auto are independent.
> > > >
> > > >But don't you think that it's getting closer to the template
semantics?
> > > >If so then using template syntax here is more consistent.
> > >
> > > Template semantics are used to introduce a type which can be provided
> > > by the user of the code. auto semantics would be used to provide a
type
> > > which is provided by the author of the code. I think conflating the
two
> > > is confusing.
> >
> > Sorry, I haven't made myself clear. I meant "it's getting closer to
> > the template function type parameter deduction semantics".
>
> To recap, making sure I understood: you are saying (I think) that
>
> template<typename T> const T& x = "abc";
>
> is better than
>
> const auto& x = "abc";
>
> because the former is clearly analogous to
>
> template<typename T>
> void foo(const T& x){
> }
>
> foo("abc");
>
> What I meant (but didn't say very well) was that adopting this syntax for
> auto in this situation would really suggest adopting it for the function
> return type situation, and that this
>
> template<typename T> // return type, user shouldn't specify
> template<typename U> // template parameter, user should specify
> T foo(){
> // ...
> }
>
> is confusing.
>
> So... what I learned so far:
> 1. Auto (in whatever form) is not a magic bullet
> 2. Auto does not play nice with c-style arrays and strings
> 3. Auto _really_ does not play nice with recursion.
> 4. It would be necessary yet painful to write asserts to check that the
> constraints on the return type of an auto function hold.
>
> and the question: Is it worth all that? I still think so, but I can
> definitely
> see other people's mileage varying :-)
>
> Emily.
>
>
>
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Mon, 25 Feb 2002 16:19:01 GMT Raw View
"Craig Tiller" <ctiller@bigpond.net.au> wrote in message
news:_1oe8.9508$RV3.34399@news-server.bigpond.net.au...
> What if we had templatized typedefs with automatic resolution of
typenames,
> similar to functions...
>
> namespace std
> {
> template <class T> typedef T auto;
> }
>
> std::auto value = f(); // automatically resolves T from return type of f
>
> Then if we needed a more restricted form, we could do so... (thinking
aloud
> now)
>
> template <class T> typedef pair<int,T> IntFirstPair;
> template <class T> IntFirstPair<T> func( int i ) { ... }
>
> IntFirstPair value = func(3);
>
> This way, we get the auto semantics, in a user controllable fashion when
we
> need it - so if we wanted to leave more information about the type in the
> function call point, then we can...
>
/That/ is too cool. I like the fact that there's no need for a new keyword
and that you're hijacking another feature that people want anyway to do the
same job. However, I worry about what happens when we have
partially-specialized typedef templates (and yes, people /do/ want that):
template <class T> typedef pair<int,T> IntFirstPair;
template <class T> typedef pair<int, T> IntFirstPair<T*>;
template <class T, class U> IntFirstPair<T> g(U) { ... }
Now if I call g(X), is it ambiguous? I ask because it seems like a very
similar problem to what rightly happens when you use the current typedef
template workaround as a function template argument:
template <class T>
void h(my_typedef<T>::type x) { ... }
The problem is that it's a nondeduced context. Since the workaround is
functionally (if not syntactically) equivalent to true typedef templates, it
seems to me that you'd face the same problem in any context that requires
deduction.
> Also note that in the second example, we get a much (much) nicer way of
> expressing
> function return types for complicated examples, which I feel is a much
> better method than
> trying to get the compiler to deduce it (which just makes me feel all
wrong)
It seems to me as though you /are/ asking the compiler to deduce it. What am
I missing?
Also, if I write:
template <class T, U, V>
std::pair<U,V> f(T) {...}
Do you expect it to deduce U and V even though std::pair is not a typedef
template?
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Juan Carlos Arevalo Baeza" <jcab__nospam__please__@JCABs-Rumblings.com>
Date: Mon, 25 Feb 2002 17:55:05 GMT Raw View
http://www.JCABs-Rumblings.com
"Dave Harris" <brangdon@cix.co.uk> wrote in message
> In other words, as if the "auto" simply introduced an implicit template
> parameter. In fact, if we allowed template deduction from return types
> where the function body is visible:
>
> template <typename X, typename Y, typename R>
> R max( X x, Y y ) {
> return x < y ? y : x;
> }
>
> long r = max( 99, 42L ); // OK! R deduced to long.
>
> then this form of "auto" becomes redundant.
I think we're confusing things here... What's the purpose of "auto" or
"let" constructs? It is to let the compiler decide what type to assign to a
new name. How can the compiler deduce the type of a variable or the return
type of a function? By examining either the expression assigned to the
variable, or the expression returned from the body of the function. In order
to do that, the compiler must be able to see either of those in the
declaration of the name in question. And that means that neither the
variable can remain uninitialized nor can it be extern-declared, nor can the
function declaration be a forward.
Now, those restrictions are logical, sensible and necessary. So we could
live with them. They do mean that, if put in a header file, the function
should be a template or inline, and the variable should be a const. Probably
should force the compiler to make sure they are not considered multiple
definitions at link time.
About the syntax, what about using "auto" to mark specific template
parameters as auto-computable? This would tell the compiler our intentions
better than anything else:
template < auto typename U > U var1; // compiler error: missing initializer!
template < auto typename U > U var2 = 1; // OK: U is integer.
template < auto typename U > U var3 = sin(6); // OK: U is double.
template < typename X, typename Y, auto typename R >
R max1(X x, Y y); // Compiler error: missing body!
template < typename X, typename Y, auto typename R >
R max2(X x, Y y) {
return int(x < y? y: x); // R deduced to be int.
}
template < typename X, typename Y, auto typename R >
R max3(X x, Y y) {
return x < y? y: x; // R can be deduced at instantiation time.
}
long k1 = max3(1, 2); // OK: R is int.
long k2 = max3(1, 2L); // OK: R is long.
No ambiguity that I can see (please, argue this if you see any), and it
brings a definitely useful feature into the language.
Salutaciones,
JCAB
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Tue, 26 Feb 2002 17:58:28 GMT Raw View
Emily Winch wrote:
>
> This does sound like a sticky patch :-( It's a sticky patch in typeof, too.
Yes and no. With 'auto' you have no option but rely on compiler's
brain in flow analisys and return type deduction. With 'typeof' the
return type is completely under your control. If the function is
recursive, it is possible to rewrite the typeof operand so that it's not
recursive (e.g. replace it with equivalent, but simplified expression
which should have the same type as the real return expression).
There's one more thing that's worrying me: How does a compiler find
out whether it can deduce the return type or not? It seems to me that it
can make the decision only after some decent flow analysis. Of course,
this flow analysis would be quite simple for trivial functions like
max(). But in the most general case flow analysis is tricky.
Traits and policies tend to introduce 'obscure' code like unreachable
blocks, 'if' conditions that are always true/false. As the result, some
'return' statements may be unreachable which in turn may affect whether
the function type is self-dependent... I can also mention that flow
analysis belongs to the realm of optimization, which is usually
performed _after_ the source code has been parsed and prooved
syntactically correct. Whereas 'auto' should be resolved _during_ this
first compilation pass...
> template<typename T>
> auto foo() {
> compile_time_assert<is_sane_foo_return_type<typeof(foo<T>())> >();
> // ...
> }
Here you are then. typeof(foo<T>()) can be deduced no earlier then
the compiler has analised the _whole_ body of this function. Therefore
it cannot be used in the body of this function.
> > > The compiler guesses the actual type of "abc".
> >
> > I.e. const char[4]? It's not always what I want. And it's plain wrong
> > for array initializer because if
> >
> > int x[5];
> > auto y = x;
> >
> > is treated like "int y[5] = x;" then this line is ill-formed.
>
> If you _don't_ want the actual type, I think you just don't use auto. To me
> that looks like a problem with c-style arrays and strings, not a problem
> with auto.
The rules of deduction dictates that if the initializer is an array
and the variable is not a reference then array-to-pointer conversion
take place and the type of the variable is "pointer to array element".
If the variable is a reference, then its type is deduced as "reference
to array", no conversion is applied. This is a good rule for function
arguments and it is reasonable for local variables as well.
So, if 'auto' is implemented via template, the problem is solved. If
'auto' is a keyword, it should behave the same way as template.
> To recap, making sure I understood: you are saying (I think) that
>
> template<typename T> const T& x = "abc";
>
> is better than
>
> const auto& x = "abc";
>
> because the former is clearly analogous to
>
> template<typename T>
> void foo(const T& x){
> }
>
> foo("abc");
Yes, that's exactly what I was saying.
> What I meant (but didn't say very well) was that adopting this syntax for
> auto in this situation would really suggest adopting it for the function
> return type situation, and that this [example skipped] is confusing.
I agree that template-like syntax applied to the function return type
looks cumbersome. I'm arguing that function return types should not be
deduced. And thus, there's no need for automatic syntax here.
> and the question: Is it worth all that? I still think so, but I can
> definitely
> see other people's mileage varying :-)
Let's try to summarise the pros and contras of these proposals
(please, correct me if I've forgotten some)
Auto:
+ Brevity. Declarations are simple, easy to teach and easy to read.
+ Enough power to declare reference variables.
- Declarations look asif 'auto' was a type name, but it isn't.
E.g. "auto x = i, z = j;" unlike "int x = i, z = j;" may introduce
the variables x and z of different types if types of i and j are
different.
- Deduced type is anonymous. Bad for template function arguments.
- Hard to implement for function return types.
Template-like syntax:
+ Consistency with other template declarations.
+ More flexible compared to 'auto'
- More text to type compared to 'auto'. This can be simplified if we
had #defined auto, auto_ref and auto_constref, but this will likely
require a new header file and all the headache that follows.
- Automatic deduction is hard to implement for function return types.
Typeof:
+ Can be used in any place where type is required. E.g. in new
expression or in a typedef.
+ Does not require an initializer. (good for class data members and
return values)
+ Already implemented in g++
- Usually initializer expression has to be repeated twice - bad for
readability and support
And the list of possible applications of these proposals (as I see it):
class data members: typeof
declaration of global/static variables: typeof
local variables: auto / template
function arguments: template
function return type: typeof
type declarations: typeof / template
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 26 Feb 2002 18:09:13 GMT Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message
news:<memo.20020221211127.15983A@brangdon.madasafish.com>...
> david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> > export? explicit instantiation?
> > You need to be able to deduce the return type without seeing the
> > function body.
> With export, the compiler can insist on seeing the function body
> before the implicit instantiation.
How the compiler works is implementation defined. Even without
templates, a compiler can insist on seeing the function body when
generating the call.
In the end, it is a quality of implementation issue. A compiler which
required the function body before allowing the call (template or no)
would be a step backwards -- current compilers won't do implicit
instantiation without the body, but they will still compile the client
code.
At some point, of course, either the function body source code, or the
compiled version of it (if the function is exported) must be available
to the compiler if it is to instantiate the function. Ideally, of
course, we'd like to just compiler the function body (template or no),
put it into a library file like any other function, and let the
compiler take care of all of the other details. I have a sneeky
feeling, however, that we aren't going to get this, or even anything
close, and that when the function body becomes available, you will
have to somehow explicitly trigger the recompilation of at least some
of the client code in order to get the implicit instantiations.
--
James Kanze mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orient e objet
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany, T l.: +49 (0)69 19 86 27
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Carl Nygard" <cjnygard@fast.net>
Date: Tue, 26 Feb 2002 20:04:43 GMT Raw View
In article <u7ktri17rq840b@corp.supernews.com>, "Juan Carlos Arevalo
Baeza" <jcab__nospam__please__@jcabs-rumblings.com> wrote:
> http://www.JCABs-Rumblings.com
> "Dave Harris" <brangdon@cix.co.uk> wrote in message
>
>> In other words, as if the "auto" simply introduced an implicit template
>> parameter. In fact, if we allowed template deduction from return types
>> where the function body is visible:
>>
>> template <typename X, typename Y, typename R> R max( X x, Y y ) {
>> return x < y ? y : x;
>> }
>>
>> long r = max( 99, 42L ); // OK! R deduced to long.
How? 99 < 42, whether they are ints or longs or whatever, so R is int,
which is cast (coerced) to long.
>>
>> then this form of "auto" becomes redundant.
>
[snip]
> template < typename X, typename Y, auto typename R > R max3(X x, Y y) {
> return x < y? y: x; // R can be deduced at instantiation time.
> }
>
> long k1 = max3(1, 2); // OK: R is int.
> long k2 = max3(1, 2L); // OK: R is long.
>
> No ambiguity that I can see (please, argue this if you see any), and
> it
> brings a definitely useful feature into the language.
for(long i = 0; i < 10; ++i){
for(double j = 0.0; j < 10.0; ++j){
cout << "Result: " << max3(i, j) << endl;
}
}
Even in this trivial example, it seems to me that the compiler could not
deduce the proper ostream code without unwrapping the loops, and actually
pre-executing the code...
And if you require the args to max3 to be constant values, then I don't see
what you gain. Using the example above:
long r = max( 99, 42L );
is rewritten with a little human brain-power as:
long r = 99;
Regards,
Carl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Wed, 27 Feb 2002 03:46:18 GMT Raw View
Dave Harris wrote:
>
> We have 3 proposals: auto, template-like declarations and typeof. What I
> am unclear about is the relationship between the template-like
> declarations, and typeof. Both are powerful tools. Can either do things
> the other cannot? Do we need both?
In my reply to Emily Winch I've tried to summarize the applicability
of each of the techniques proposed. In brief, yes, I think we need both,
each of them has its best application.
> > However unlike other types it cannot be used in function arguments,
> > function return type, class data members... That's why I was advocating
> > template-like syntax: it's consistent and it can be used everywhere:
>
> Hmmm. Is there any reason auto cannot be used for function arguments? Eg
You've named this reason: 'auto' will introduce anonymous type, which
can't be reused in the body of the function.
> void print( ostream &os, auto const &x ) {
> os << x << "\n";
> }
>
> would be syntactic sugar for:
>
> template <typename X>
> void print( ostream &os, X const &x ) {
> os << x << "\n";
> }
>
> The auto form is more pleasant, less cluttered.
We already have template syntax for functions. IMHO creating a new
syntax for template functions that is very similar to the syntax of
non-template function is misleading.
> > Template type parameters used as function return types are not
> > deduced.
>
> True, but that is a rather arbitrary restriction. Why shouldn't:
>
> template <typename X, typename Y, typename R>
> R max( X x, Y y ) {
> return x < y ? y : x;
> }
>
> allow R to be deduced as the type of the return expression?
I can think of some examples where deducing return type is not easy.
For one, consider a recursive function whose return type depends on
itself.
> The supposed advantage is that the return type can be deduced without
> looking at the function body. In practice it seems to put much of the
> function body *into* the declaration. The redundancy, the repeating of
> expressions, is something I don't like about typeof.
Yes, this redundancy is annoying in simple functions. But in the most
general case, a function may have several return statements with
expressions of different types. Or it may be recursive or otherwise
depends on its own type. In such cases automatic return type deduction
may confuse the compiler (or require decent flow analisys) and hide
programming errors.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Craig Tiller" <ctiller@bigpond.net.au>
Date: Wed, 27 Feb 2002 03:47:05 GMT Raw View
I think the point of clarification needs to be that in my view of this
thing,
function return types need to be explicitly written out by the programmer,
because I honestly dont see the need for a function to return more than one
type for a set of input types, BUT template typedefs give us the means to
make
it easier to write out what a function returns (more on this in a moment).
The "cool" bit is that if you use a template (and I think It'll work with
any template...
be it a class, or a typedef) as a declarator, then the compiler
matches up the types all by itself... so the following two things are
equivalent (given Foo):
template <class T> class Foo { ... };
....
Foo f = Foo<int>(); // deduce T for f to be int
or...
template <class T> typedef Foo<T> Bar<T>;
Bar f = Foo<int>(); // or Bar<int>() -- deduce <T> on f to be int
This gives us our "auto" type for free.
Then, with templatized typedefs (this is the more in a moment), we get a
nice way to
say what the return value of a function should be...
namespace Private
{
template <class A, class B, class C> typedef triplet<
FunkyType<A,B>,FunkyType<B,C>,FunkyType<C,A> > FooRet; // chosen to be
overtly verbose :P
}
template <class A, class B> Private::triplet<A,B,int> foo(int i, A a, B b)
{} // much nicer than it would have been, and no compiler deduction
Originally I hadn't wanted the compiler to do that deduction based on the
return code, and I'm yet to think of a
way that would be useful, but if someone can really convince me of why it
needs to be there, then maybe I would
accept a syntax like:
template <class A, class B> Private::triplet foo(int i, A a, B b) {} //
compiler deduces return type based on what foo returns
My *big* concern though is on how many code paths this is going to
generate... consider (contrived to be brief):
class A
{
public:
bool next_val() { return rand()%7 == 0; }
};
class B
{
public:
bool next_val() { return rand()%28391 == 0; }
};
std::auto example_func( bool f )
{
if (f)
return A();
else
return B();
}
bool ooh_bad_consequences( int i, std::auto c )
{
if (i)
return ooh_bad_consequences( i-1, example_func(c.next_val()) );
else
return c.next_val();
}
int main()
{
srand( time(NULL) );
return ooh_bad_consequences( 10000, A() );
}
How exactly should we generate code for that? - we've just added the
facility to
(naively if its a big program with complicated subsystems) add *HUGE*
compiled
code complexity fairly easily from just one point in the source - and that
just seems
to run against the grain of what C++ is all about.
"David Abrahams" <david.abrahams@rcn.com> wrote in message
news:a5dhjs$afv$1@bob.news.rcn.net...
>
> "Craig Tiller" <ctiller@bigpond.net.au> wrote in message
> news:_1oe8.9508$RV3.34399@news-server.bigpond.net.au...
> > What if we had templatized typedefs with automatic resolution of
> typenames,
> > similar to functions...
> >
> > namespace std
> > {
> > template <class T> typedef T auto;
> > }
> >
> > std::auto value = f(); // automatically resolves T from return type of f
> >
> > Then if we needed a more restricted form, we could do so... (thinking
> aloud
> > now)
> >
> > template <class T> typedef pair<int,T> IntFirstPair;
> > template <class T> IntFirstPair<T> func( int i ) { ... }
> >
> > IntFirstPair value = func(3);
> >
> > This way, we get the auto semantics, in a user controllable fashion when
> we
> > need it - so if we wanted to leave more information about the type in
the
> > function call point, then we can...
> >
>
> /That/ is too cool. I like the fact that there's no need for a new keyword
> and that you're hijacking another feature that people want anyway to do
the
> same job. However, I worry about what happens when we have
> partially-specialized typedef templates (and yes, people /do/ want that):
>
> template <class T> typedef pair<int,T> IntFirstPair;
> template <class T> typedef pair<int, T> IntFirstPair<T*>;
> template <class T, class U> IntFirstPair<T> g(U) { ... }
>
> Now if I call g(X), is it ambiguous? I ask because it seems like a very
> similar problem to what rightly happens when you use the current typedef
> template workaround as a function template argument:
>
> template <class T>
> void h(my_typedef<T>::type x) { ... }
>
> The problem is that it's a nondeduced context. Since the workaround is
> functionally (if not syntactically) equivalent to true typedef templates,
it
> seems to me that you'd face the same problem in any context that requires
> deduction.
>
> > Also note that in the second example, we get a much (much) nicer way of
> > expressing
> > function return types for complicated examples, which I feel is a much
> > better method than
> > trying to get the compiler to deduce it (which just makes me feel all
> wrong)
>
> It seems to me as though you /are/ asking the compiler to deduce it. What
am
> I missing?
>
> Also, if I write:
>
> template <class T, U, V>
> std::pair<U,V> f(T) {...}
>
> Do you expect it to deduce U and V even though std::pair is not a typedef
> template?
>
> -Dave
>
>
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Craig Tiller" <craig@clinicdesign.com.au>
Date: Wed, 27 Feb 2002 16:15:30 GMT Raw View
> Also, if I write:
>
> template <class T, U, V>
> std::pair<U,V> f(T) {...}
>
> Do you expect it to deduce U and V even though std::pair is not a typedef
> template?
>
> -Dave
In a function declaration, see previous post,
as a variable declaration, I suppose the syntax
template <class U, class V> std::pair<U,V> x = f(whatever);
could be useful... ie you can bang in a template statement before any
declaration
and have the compiler figure things out
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Juan Carlos Arevalo Baeza" <jcab__nospam__please__@JCABs-Rumblings.com>
Date: Wed, 27 Feb 2002 10:34:24 CST Raw View
"Carl Nygard" <cjnygard@fast.net> wrote in message
news:3c7be541_2@news7.fast.net...
> In article <u7ktri17rq840b@corp.supernews.com>, "Juan Carlos Arevalo
> Baeza" <jcab__nospam__please__@jcabs-rumblings.com> wrote:
>
> > template < typename X, typename Y, auto typename R > R max3(X x, Y y) {
> > return x < y? y: x; // R can be deduced at instantiation time.
> > }
>
> for(long i = 0; i < 10; ++i){
> for(double j = 0.0; j < 10.0; ++j){
> cout << "Result: " << max3(i, j) << endl;
> }
> }
>
> Even in this trivial example, it seems to me that the compiler could not
> deduce the proper ostream code without unwrapping the loops, and actually
> pre-executing the code...
I don't see it. Why? The compiler sees "max3(i, j)", knows the types of
"i" and "j", so it can instantiate the template. The "auto" in the last
template argument would indicate to the compiler that that type should be
deducible from the body of the function. And it is indeed deducible, so
that's why I say there's no ambiguity.
> And if you require the args to max3 to be constant values, then I don't
see
> what you gain.
I never said that. I just provided constants for brevity. The args must
have a known type in order for the template to be instantiated, but that's
all. And that's already the rule with template functions that use deduced
arg types.
> Using the example above:
>
> long r = max( 99, 42L );
>
> is rewritten with a little human brain-power as:
>
> long r = 99;
Yes, but that's not the point.
Look at this expression:
99 < 42L ? 99: 42L
What's its type? "long int" I think (the standard sounds very obscure
about this point, actually, ref. 5.16). Why? Because the compiler sees the
types of either side of the ":" (int and long int) and decides that the 99
should be cast to "long int". Or else I'm wrong and it should cast the "long
int" to plain int. But that's besides my point. The fact is that the
compiler decides the resulting type of this expression from the type of the
values it finds inside.
Now, what happens (or should happen? ;-) when I write "max( 99, 42L );"?
The compiler assigns "int" and "long int" to the types X and Y. And then it
can deduce the type R, from the body of the function. That's when it
instantiates the function. Wether it then uses compile-time evaluation to
eliminate the function completely is besides the point.
Salutaciones,
JCAB
http://www.JCABs-Rumblings.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Wed, 27 Feb 2002 20:45:15 GMT Raw View
On "let" vs. "auto":
I can write
int foo = 1;
static int bar = foo;
within a function.
If "auto" is used for implicit type declaration,
I can write
static auto foo = bar;
which contradicts the current meaning of "auto"
and I can even write
auto auto foo = bar;
which is a bit much. Which "auto" is which?
This is an indication that we're overloading
a keyword excessively.
On the other hand, would we prefer
let static foo = bar;
or
static let foo = bar;
(As for the template and return value issues, I
have no opinion; those are too obscure for me.)
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Craig Tiller" <ctiller@bigpond.net.au>
Date: Wed, 27 Feb 2002 21:15:08 GMT Raw View
see with my way of thinking, "auto" or "let" becomes a type - which I figure
should be
std::deduced, but hey :)... declared as
template <class T> typedef T deduced;
and use the compilers pattern matching engine work out what T should be.
"John Nagle" <nagle@animats.com> wrote in message
news:3C7D36C6.5020509@animats.com...
> On "let" vs. "auto":
>
> I can write
>
> int foo = 1;
> static int bar = foo;
>
> within a function.
>
> If "auto" is used for implicit type declaration,
> I can write
>
> static auto foo = bar;
>
> which contradicts the current meaning of "auto"
>
> and I can even write
>
> auto auto foo = bar;
>
> which is a bit much. Which "auto" is which?
> This is an indication that we're overloading
> a keyword excessively.
>
> On the other hand, would we prefer
>
> let static foo = bar;
> or
> static let foo = bar;
>
> (As for the template and return value issues, I
> have no opinion; those are too obscure for me.)
>
> John Nagle
> Animats
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Thu, 28 Feb 2002 16:11:23 GMT Raw View
John Nagle wrote:
>
> [...] Which "auto" is which?
> This is an indication that we're overloading
> a keyword excessively.
If we end up introducing 'auto' as a keyword, I'd vote for deleting
the old meaning of 'auto' from the standard. After all, in its current
state 'auto' isn't used much (if ever used at all).
Then 'auto' will not be overloaded and will serve only one purpose:
type deduction.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 28 Feb 2002 22:59:23 GMT Raw View
cjnygard@fast.net (Carl Nygard) wrote (abridged):
> >> template <typename X, typename Y, typename R> R max( X x, Y y ) {
> >> return x < y ? y : x;
> >> }
> >>
> >> long r = max( 99, 42L ); // OK! R deduced to long.
>
> How? 99 < 42, whether they are ints or longs or whatever, so R is int,
> which is cast (coerced) to long.
The type R is bound to the type of the return expression, which I'll write
as (bool?int:long), which is long. It does not depend on the run-time
values. It only depends on the existing rules for merging the branches of
the ?: operator.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 28 Feb 2002 23:31:19 GMT Raw View
jcab__nospam__please__@JCABs-Rumblings.com (Juan Carlos Arevalo Baeza)
wrote (abridged):
> About the syntax, what about using "auto" to mark specific template
> parameters as auto-computable? This would tell the compiler our
> intentions better than anything else:
I don't think anything is gained. Also, I don't think it is backwards
compatible. Today I can write:
template <typename T>
T max( T a, T b ) {
return (b < a) ? a : b;
}
int i = max( 2, 3 ); // OK!
and the compile will "auto" deduce the types. Are you saying I must
instead write:
template <auto typename T>
T max( T a, T b ) {
return (b < a) ? a : b;
}
If so, then it is not backwards compatible. If not, then the return case
is not consistent with the argument case. Why should we have to say "auto"
for some types and not others?
> No ambiguity that I can see
Agreed, but there was no ambiguity without the "auto" either.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 28 Feb 2002 23:31:36 GMT Raw View
kanze@gabi-soft.de (James Kanze) wrote (abridged):
> > With export, the compiler can insist on seeing the function body
> > before the implicit instantiation.
I am thinking here of 14/8
[Note: an implementation may require that a translation unit contain-
ing the definition of an exported template be compiled before any
translation unit containing an instantiation of that template. ]
Note that it is talking about different compilation units. I think you
thought I meant within a single compilation unit.
> How the compiler works is implementation defined. Even without
> templates, a compiler can insist on seeing the function body when
> generating the call.
>
> In the end, it is a quality of implementation issue. A compiler which
> required the function body before allowing the call (template or no)
> would be a step backwards -- current compilers won't do implicit
> instantiation without the body, but they will still compile the client
> code.
Currently the option of deducing a return type is not available. A
compiler which allowed this, and which insisted on seeing the compilation
unit with the template's body before any compilation unit with an
instantiation of that template, *if and only if* the template used return
type deduction, would not be a step backwards. Code which did not use the
new feature would not be affected.
> Ideally, of course, we'd like to just compiler the function
> body (template or no), put it into a library file like any
> other function, and let the compiler take care of all of the
> other details.
Yes. If return type deduction is adopted, the library will have to include
enough information to allow the deduction of return types from calls. This
makes a compiled "export" template library a rather rich data store, but
then it has to be anyway to support "export".
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 28 Feb 2002 23:31:55 GMT Raw View
ctiller@bigpond.net.au (Craig Tiller) wrote (abridged):
> My *big* concern though is on how many code paths this is going to
> generate... consider (contrived to be brief):
>
> class A
> {
> public:
> bool next_val() { return rand()%7 == 0; }
> };
>
> class B
> {
> public:
> bool next_val() { return rand()%28391 == 0; }
> };
>
> std::auto example_func( bool f )
> {
> if (f)
> return A();
> else
> return B();
> }
I don't see how a return type can be deduced for example_func(), because
it has multiple returns with incompatible types. Type-deduction must be
independent of the runtime values.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 28 Feb 2002 19:03:40 CST Raw View
igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
> There's one more thing that's worrying me: How does a compiler find
> out whether it can deduce the return type or not? It seems to me that it
> can make the decision only after some decent flow analysis.
In my view, any deduced return type should not require flow analysis.
Either multiple returns are disallowed, or else they are combined in a
similar way to branches of the condition operator. If the latter:
template <typename R, typename T>
R func( T t ) {
if (t >= 0)
return 1;
throw "negative!";
return 1L; // Not reached.
}
R is always deduced to long, even though the last line of the function is
unreachable.
This principle is orthogonal to questions of syntax. It makes the problem
a bit more tractable. It is still possible to write code in which the
deduced types won't be obvious, but then that's already true of templates.
(Eg typelists.)
> Let's try to summarise the pros and contras of these proposals
Useful summary, thanks.
> Auto:
> - Deduced type is anonymous. Bad for template function arguments.
Although it avoids some problems of the template syntax, by preventing
multiple uses. Eg:
template <typename R, typename T>
R func( T t ) {
R r1 = 42;
// R r2 = "Hello, world";
return R();
}
Uses of R within the function make me feel a bit uncomfortable. Is R
supposed to be deduced from the initialiser of r1? If so, what happens if
there is a second initialiser?
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Thu, 14 Feb 2002 17:42:46 GMT Raw View
"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
news:a4gq0l$b3e$1@reader0.news.uk.quza.net...
> It seems a bit hairy, the way that something like (contrived example
ahead)
>
<snip hairy problems>
> > 2. Isn't there a bigger problem here because now callers can't deduce
the
> > return type given just a declaration?
>
> Mostly the callers can write
>
> auto T t = foo< /* whatever */ >();
>
> But if they need more than that, maybe they could write
>
> typeof(foo< /* whatever */ >()) t;
Can you think of a syntax which solves these problems? I can't: it seems
like there are lots of hairy problems with deducing function return types
regardless of the syntax you choose.
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Thu, 14 Feb 2002 18:42:45 GMT Raw View
David Abrahams wrote ...
>"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
>news:a4gq0l$b3e$1@reader0.news.uk.quza.net...
>
>> It seems a bit hairy, the way that something like (contrived example
>ahead)
>
><snip hairy problems>
>
>Can you think of a syntax which solves these problems? I can't: it seems
>like there are lots of hairy problems with deducing function return types
>regardless of the syntax you choose.
The "auto" thing solves the particular problems I mentioned.
template<typename T, typename U> U foo(T t);
is clearly different from
template<typename T, typename U> auto foo(T t);
The second form doesn't allow the user to accidentally specify the "auto"
type when calling the function.
I'm not (yet) convinced that there's a problem with making people write
auto x = foo<int, double>(1);
and they can still write
const auto& x = foo<int, double>(1);
I'm sure there are other problems with "auto" but I don't know what they
are.
Multiple returns in an auto-returning function just have to return the same
type, or else be ambiguous, at which point the author just has to work out
the return type themselves like we do at the moment.
What am I missing ?
Emily
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Thu, 14 Feb 2002 19:05:06 GMT Raw View
"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
news:a4h02m$21t$1@helle.btinternet.com...
> The "auto" thing solves the particular problems I mentioned.
>
> template<typename T, typename U> U foo(T t);
>
> is clearly different from
>
> template<typename T, typename U> auto foo(T t);
>
> The second form doesn't allow the user to accidentally specify the "auto"
> type when calling the function.
That doesn't seem so much worse than any other mistake to make it worthwhile
taking measures to avoid it.
> I'm not (yet) convinced that there's a problem with making people write
>
> auto x = foo<int, double>(1);
>
> and they can still write
>
> const auto& x = foo<int, double>(1);
>
> I'm sure there are other problems with "auto" but I don't know what they
> are.
You can't do this with auto:
template <class II, class OI> bool(*copier)(II,II,OI) = ...;
Some people also want to be able to add a block, so that deduced II and OI
can be re-used.
> Multiple returns in an auto-returning function just have to return the
same
> type, or else be ambiguous, at which point the author just has to work out
> the return type themselves like we do at the moment.
>
> What am I missing ?
export? explicit instantiation?
You need to be able to deduce the return type without seeing the function
body.
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 14 Feb 2002 20:58:43 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message news:<a4f3q7$8la$1@bob.news.rcn.net>...
> "Daveed Vandevoorde" <google@vandevoorde.com> wrote in message
> news:52f2f9cd.0202131157.5652aa30@posting.google.com...
[...]
> > Your proposed syntax matches another extension I've
> > toyed with: object templates. I.e., after your first
> > declaration, I would expect to be able to refer to an
> > object "x<int>" (of type int).
> >
> > (A matter of taste of course.)
>
> I'm not sure. What's the initialization order of instantiations of x<T>? It
> seems to present a few problems and it doesn't solve any that I've had. It
> also seems to be incompatible with mmy intended meaning (deduced type in
> declaration). Does it solve some real-world problem you've encountered?
template<class T> bool const is_const = false;
template<class T> bool const is_const<T const> = true;
;-)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 14 Feb 2002 20:58:54 GMT Raw View
david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> The best suggestion I've heard so far is:
>
> template <class T> T x = ... ;
Although that will often be longer and more complex than the code it
replaces.
> which would also admit:
>
> template <class T> T const* p = ... ;
> template <class T, class U> T const& (*f)(U**) = ... ;
>
> etc.
Let's not get carried away. If necessary, we can achieve a similar effect
via an extra template function, so the extra generality of this syntax
isn't really buying us much. I think it is more important to keep the
common case simple and uncluttered.
Stroustrup once wrote of C++:
It's main purpose was to make writing good programs easier
and more pleasant for the individual programmer. [C++PL $1.4]
In this spirit, even if we have "typeof" and/or some template syntax like
the above, I hope we will also have "auto" or "let". They are more
pleasant to use.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Thu, 14 Feb 2002 21:53:44 GMT Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20020214195818.5663A@brangdon.madasafish.com...
> david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> > The best suggestion I've heard so far is:
> >
> > template <class T> T x = ... ;
>
> Although that will often be longer and more complex than the code it
> replaces.
In those cases we don't need this feature. It's people working with
expression templates, for example, that need it.
>
> > which would also admit:
> >
> > template <class T> T const* p = ... ;
> > template <class T, class U> T const& (*f)(U**) = ... ;
> >
> > etc.
>
> Let's not get carried away. If necessary, we can achieve a similar effect
> via an extra template function, so the extra generality of this syntax
> isn't really buying us much.
As long as you have a way to distinguish values from references a la
auto const& x = ... ;
vs
auto x = ... ;
Then I suppose I agree.
> I think it is more important to keep the
> common case simple and uncluttered.
...as long as we don't give up some important capabilities (I'm not saying
we would be).
> Stroustrup once wrote of C++:
> It's main purpose was to make writing good programs easier
> and more pleasant for the individual programmer. [C++PL $1.4]
>
> In this spirit, even if we have "typeof" and/or some template syntax like
> the above, I hope we will also have "auto" or "let". They are more
> pleasant to use.
You have personal experience? Where can I buy your compiler? ;-)
I too would like to have auto. I remember when I proposed that about a year
ago some core language lawyers found some things to argue with, though. I'd
rather not introduce a new keyword (let).
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Thu, 14 Feb 2002 23:32:18 GMT Raw View
David Abrahams wrote in message ...
>
>"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
>news:a4h02m$21t$1@helle.btinternet.com...
>
>> The "auto" thing solves the particular problems I mentioned.
>>
>> template<typename T, typename U> U foo(T t);
>>
>> is clearly different from
>>
>> template<typename T, typename U> auto foo(T t);
>>
>> The second form doesn't allow the user to accidentally specify the "auto"
>> type when calling the function.
>
>That doesn't seem so much worse than any other mistake to make it
worthwhile
>taking measures to avoid it.
I think there is a lot of confusion potential in having one syntax to do two
slightly different things, _with different usage_, specifically when those
two things are usually found in consecutive lines of code. I think it's
worthwhile taking measures to avoid that. Other people's Mileage Probably
Varies.
>> I'm not (yet) convinced that there's a problem with making people write
>>
>> auto x = foo<int, double>(1);
>>
>> and they can still write
>>
>> const auto& x = foo<int, double>(1);
>>
>> I'm sure there are other problems with "auto" but I don't know what they
>> are.
>
>You can't do this with auto:
>
>template <class II, class OI> bool(*copier)(II,II,OI) = ...;
Am I right in thinking that there isn't any difference between that and
auto copier = .... ;
unless II and OI are available afterwards? which is what you said next....
>Some people also want to be able to add a block, so that deduced II and OI
>can be re-used.
But we can still deduce II and OI anyway, something like
auto copier = .....;
typedef deduce_params<typeof copier>::first II;
>> What am I missing ?
>
>export? explicit instantiation?
>You need to be able to deduce the return type without seeing the function
>body.
If I write
template<typename> class foo;
typedef typename foo<int>::type type;
That doesn't work either. So I don't do that :-)
Being able to have a function template auto-ified _and_ exported would be
nice and all, but being able to have one or the other would be pretty good
too.
Emily
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 15 Feb 2002 17:25:56 GMT Raw View
nagle@animats.com (John Nagle) wrote (abridged):
> We could probably tolerate "let" as a keyword; it's not a
> popular variable name.
It's an abbreviation of "letter". It's also a word in its own right, with
many dictionary meanings that could be useful in code. I think this
keyword would definitely break some old code.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Fri, 15 Feb 2002 17:26:27 GMT Raw View
"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
news:a4hfhv$c8u$1@paris.btinternet.com...
>
> David Abrahams wrote in message ...
>
> >You can't do this with auto:
> >
> >template <class II, class OI> bool(*copier)(II,II,OI) = ...;
>
> Am I right in thinking that there isn't any difference between that and
>
> auto copier = .... ;
Just error checking. In your case, copier could end up being an int.
> But we can still deduce II and OI anyway, something like
>
> auto copier = .....;
> typedef deduce_params<typeof copier>::first II;
You're right this time.
> If I write
>
> template<typename> class foo;
>
> typedef typename foo<int>::type type;
>
> That doesn't work either. So I don't do that :-)
>
> Being able to have a function template auto-ified _and_ exported would be
> nice and all, but being able to have one or the other would be pretty good
> too.
Right again (you keep doing that)!
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Fri, 15 Feb 2002 17:26:28 GMT Raw View
Emily Winch wrote:
>
> template<class T, int I>
> template<class Ret> Ret foo() {
> return /* something whose type depends on T and I */ ;
> }
>
> Which is the same phenomenon as what you're discussing, so it should really
> look the same, and I'd argue that this feature is nearly as important.
I would argue that deducing function return type is not the same as
deducing the type of local automatic variable. As far as functions are
concerned, it is always important not to mix the declaration and
definition 'cause the former is a part of contracted interface while the
latter may change and should not affect the said interface.
Strictly speaking, type deduction is only possible when there is
something to deduce from. For variables this "something" is the
initializer. For functions this "something" is a return statement
expression. Variables can be used in a context where declaration comes
along with initialization (and automatic deduction is thus possible);
but the declaration of the function return type is never in the same
place where return statement is.
To put it short: I don't see a use for any form of 'auto'
(template-style or a new keyword) in function declarations.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 15 Feb 2002 17:44:38 GMT Raw View
david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> > I think it is more important to keep the common case simple
> > and uncluttered.
>
> ...as long as we don't give up some important capabilities (I'm not
> saying we would be).
Do you see this "template" syntax as an alternative to the "typeof"
proposals? I agree we need a full-powered feature for dealing with the
hard cases. People writing expression templates are already dealing with
rather abstract and difficult code. They need powerful tools.
However, I think it is worth having some syntactic sugar to deal with the
simple cases, *in addition* to typeof/whatever. I am not a teacher, but I
would hope something like "auto" could be taught on day 1 of a C++ course,
and used very frequently. "Typeof" would be left to day 21 :-)
Could some real teachers comment on this? Would you teach "auto" before
"int"?
I was going to say that power-users are not scared of complex syntax, but
that isn't true. Indeed, they more than anyone need the simple cases to
not clutter and distract from the convoluted ones.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Fri, 15 Feb 2002 18:00:16 GMT Raw View
Dave Harris wrote:
> nagle@animats.com (John Nagle) wrote (abridged):
>
>>We could probably tolerate "let" as a keyword; it's not a
>>popular variable name.
>>
>
> It's an abbreviation of "letter". It's also a word in its own right, with
> many dictionary meanings that could be useful in code. I think this
> keyword would definitely break some old code.
Why speculate? Find out.
I suggest as a metric that if a potential keyword is not used
in a conflicting way in any widely-used, publicly-exposed code,
it is suitable for consideration. Keywords such as
"namespace" and "volatile" have been added without too much
trouble. "bool" was admittedly tough.
It's most important that there be no conflicts in widely
used headers. That's easy to check.
Searching the headers supplied with MS VC 6.x finds no
occurences of "let" in C/C++ code. The other major
development environments should be searched, along
with widely used class libraries.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Fri, 15 Feb 2002 18:19:54 GMT Raw View
Dave Harris wrote:
>
> david.abrahams@rcn.com (David Abrahams) wrote (abridged):
> > The best suggestion I've heard so far is:
> >
> > template <class T> T x = ... ;
>
> Although that will often be longer and more complex than the code it
> replaces.
It's easy to hide the nature of such declaration in a macro
#define Auto template<typename T_19253 > T_19253
and use it: Auto x = ...; You can also define Auto_ref, Auto_constref,
etc. to your taste.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Fri, 15 Feb 2002 19:43:24 GMT Raw View
John Nagle <nagle@animats.com> writes:
| Why speculate? Find out.
I said I used as a function name. That is not speculation.
| I suggest as a metric that if a potential keyword is not used
| in a conflicting way in any widely-used, publicly-exposed code,
| it is suitable for consideration.
Why the program has to be publicly-exposed before being taken into
consideration?
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Fri, 15 Feb 2002 21:30:16 GMT Raw View
Igor A. Goussarov wrote:
> I would argue that deducing function return type is not the same as
>deducing the type of local automatic variable. As far as functions are
>concerned, it is always important not to mix the declaration and
>definition 'cause the former is a part of contracted interface while the
>latter may change and should not affect the said interface.
If a function is written
template< ... >
auto foo(... );
The contracted interface is then "This function returns an object of some
type or other". This will not be affected by changing the function
definition. OK, this is useless in practice unless the author documents
some constraints on what the return type can be. But then it's the author's
responsibility to ensure that those constraints continue to be satisfied, in
the same way as constraints on the return value.
> Strictly speaking, type deduction is only possible when there is
>something to deduce from. For variables this "something" is the
>initializer. For functions this "something" is a return statement
>expression. Variables can be used in a context where declaration comes
>along with initialization (and automatic deduction is thus possible);
>but the declaration of the function return type is never in the same
>place where return statement is.
This syntax is only of any use for function templates where the return type
depends on the template parameters, and only then where the template is
not exported or explicitly instantiated. However, in this limited case, the
return statement is never far from the function declaration.
> To put it short: I don't see a use for any form of 'auto'
>(template-style or a new keyword) in function declarations.
This is the code I'm using to work out the return types of one function, in
its
const and non-const incarnations (13 lines each).
namespace detail {
template<class AssociativeList, bool IsConst>
struct get_associative_list_iterator{
typedef typename
select_type<IsConst,
const_associative_list_iterator<AssociativeList>,
associative_list_iterator<AssociativeList>
>::type type;
};
template<typename List, typename TheKey, bool IsConst>
struct tail_iterator_type{
typedef typename
select_type<IsConst,
typename List::tail_type::template
const_iterator_type<TheKey>,
typename List::tail_type::template iterator_type<TheKey>
>::type::type type;
};
template<typename List, typename TheKey, bool IsConst>
struct iterator_type_impl{
typedef typename
select_type<is_same<TheKey, typename List::key_type>::value,
typename
select_type<IsConst,
typename List::const_begin_iterator_type,
typename List::begin_iterator_type>::type,
typename
select_type<is_same<typename List::tail_type, nil>::value,
get_associative_list_iterator<nil, IsConst>,
tail_iterator_type<List, TheKey, IsConst>
>::type::type
>::type type;
};
} // namespace detail
// later on in some other class
template<typename TheKey>
struct iterator_type{
typedef typename
detail::iterator_type_impl<self_type, TheKey, false>::type type;
};
template<typename TheKey>
struct const_iterator_type{
typedef typename
detail::iterator_type_impl<self_type, TheKey, true>::type type;
};
If I had "auto" I could throw that _all_ away.
Furthermore, people _using_ this code could quit typing
typename iterator_type<foo>::type a = x.y<foo>();
and type
auto a = x.y<foo>;
With the bonus that they no longer have to look up in my documentation
that "typename iterator_type<foo>::type" is the way to work out the
return type of the function.
I think this is a reasonably typical example of the sort of hoops people
have to jump through to sort out their return types when writing
complex template code.
Emily.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Fri, 15 Feb 2002 21:39:55 GMT Raw View
David Abrahams wrote in message ...
>
>"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
>news:a4hfhv$c8u$1@paris.btinternet.com...
>>
>> David Abrahams wrote in message ...
>>
>> >You can't do this with auto:
>> >
>> >template <class II, class OI> bool(*copier)(II,II,OI) = ...;
>>
>> Am I right in thinking that there isn't any difference between that and
>>
>> auto copier = .... ;
>
>Just error checking. In your case, copier could end up being an int.
Does the user need or want any error checking on the type of "copier"
beyond the fact that the code using it compiles? I mean, if "copier" is
an int, nobody's going to have any luck trying to copy things with it. If
"copier" is a function object, they'd probably like to copy things with it.
What _is_ annoying is that there's no obvious place for the function
author to put the error checking.
I suppose he could write
template<typename T, int I>
auto foo(T t){
assert_is_sane_foo_return_type<typeof foo<T, I>(t)> ();
// other stuff
}
... blegh.
Emily
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Sun, 17 Feb 2002 10:34:11 CST Raw View
igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
> It's easy to hide the nature of such declaration in a macro
>
> #define Auto template<typename T_19253 > T_19253
>
> and use it: Auto x = ...; You can also define Auto_ref, Auto_constref,
> etc. to your taste.
True, but I am not a big fan of macros.
By the same argument, we can introduce any number of new keywords with
names like cpp0x_feature97_qrtZaQp, that are unlikely to conflict with
user variables, and encourage users to write:
#define typeid cpp0x_feature12_qrtZaQp
or whatever. I don't feel quite comfortable with this.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Tue, 19 Feb 2002 09:57:42 CST Raw View
Emily Winch wrote:
>
> If a function is written
>
> template< ... >
> auto foo(... );
>
> The contracted interface is then "This function returns an object of some
> type or other".
But this gives absolutely no information about the return type. It
isn't necessarily an object, it might be a builtin type or even a void.
So this declaration actually declare nothing useful. The whole point of
declaration is to provide a compiler with some information required to
check function call syntax, choose the proper overloaded operator (if
the result of this function is used as an argument to one) and call this
function without seeing its body. And I can see how 'auto' breaks this
concept, because now such declaration doesn't allow a compiler to
perform overload resolution. Even if no overload resolution is required,
it doesn't allow to perform a function call because it's not clear how
to treat (i.e. destruct) the returned temporary.
> > Strictly speaking, type deduction is only possible when there is
> >something to deduce from. For variables this "something" is the
> >initializer. For functions this "something" is a return statement
> >expression. Variables can be used in a context where declaration comes
> >along with initialization (and automatic deduction is thus possible);
> >but the declaration of the function return type is never in the same
> >place where return statement is.
>
> This syntax is only of any use for function templates where the return type
> depends on the template parameters, and only then where the template is
> not exported or explicitly instantiated. However, in this limited case, the
> return statement is never far from the function declaration.
Yes, it's quite common to define templated function right where it is
declared. However the use of 'auto' here will _force_ you to do so.
A function may have several return statements. Probably with
expressions of different types (e.g. it return either a pointer to
object or NULL). This would be a challenge for a compiler to guess the
correct return type. More important, it would be a challenge for the
programmer to scan the source code (possibly lots of, if the function in
question call some other functions) to figure out what the return type
of this function is. Automatic return type deduction may incorrectly
treat programmer's errors if he had used incompatible types in several
return statements.
There is a radical solution: introduce the variant type (and name it
'auto'). But the variant type will likely come with run-time type
checking and casting, which contradicts with the spitit of template
types: the latter is substituted at compile time and doesn't involve
runtime costs. So I don't suppose we need a variant type just to avoid a
lengthy function declarations. (Though, variant type probably have its
application). If we agree on this, then the return type should be fixed
and should be defined explicitly.
> > To put it short: I don't see a use for any form of 'auto'
> >(template-style or a new keyword) in function declarations.
>
> This is the code I'm using to work out the return types of one function, in
> its
> const and non-const incarnations (13 lines each).
I see. After all, how many times do you have to type the function
return type? Probably twice: at the point of declaration and at the
point of definition. Or once if you've typedefed it. I think we can
afford typing the type ( :-) ) once. 'auto' in declaration of local
variables will save us much more typing. Of course, I agree that 13
lines is too much, but nevertheless I think that the return type should
be declared explicitly.
> Furthermore, people _using_ this code could quit typing
>
> typename iterator_type<foo>::type a = x.y<foo>();
>
> and type
>
> auto a = x.y<foo>;
>
> With the bonus that they no longer have to look up in my documentation
> that "typename iterator_type<foo>::type" is the way to work out the
> return type of the function.
That's the point! In your example the return type is used twice:
first time in a fucntion declaration and the second time in the
definition of a local variable. There are cases when you want your local
variable type to match its initializer type exactly. But you don't have
to make automatic _both_ function return type (used as initializer) and
local var type. It would be enough to leave the function type fixed and
let the compiler guess the type of local variable.
As for the syntax of this automatic deduction, I've seen three
options:
1. 'auto' keyword
2. template-like declaration
3. typeof operator.
Choosing between the first two, I admit that template approach is
more powerful. 'auto' keyword can be simulated with macro "#define auto
template <typename __t> __t", but I don't see how a single 'auto'
keyword can cover all the variety of template declarations. One
particular example where the use of 'auto' is impossible is when the
initializer is either an array initializer or a string literal. Given
auto x = "abc";
what should a compiler guess:
char x[] = "abc";
const char* x = "abc";
const char (&x)[] = "abc"; ?
If we use template syntax, then the standard rules of type parameter
deduction take place and the type deduced is "const char*". If the
programmer want another meaning, he can use "template <typename __t>
const __t&" or similar. Template approach lets you create as many macros
(auto, auto_ref, auto_constref, ...) as you want. 'auto' keyword can
have more power if it was treated like a template-deduced type
parameter. Then one will be able to use
const auto& x = "abc";
map<auto, auto>& y = myMap; // here both auto are independent.
But don't you think that it's getting closer to the template semantics?
If so then using template syntax here is more consistent.
As for the typeof operator, since it can be used not only in variable
declaration but in any other place where a type name is expected (e.g.
new typeof(...)), I don't see it as an alternative to the first two
options. Using typeof for automatic type deduction doesn't make things
easier because the initializer expression must be repeated twice.
Having said this, I would like to see both typeof keyword both
template-like automatic variable declarations in the language.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: thp@cs.ucr.edu
Date: Tue, 19 Feb 2002 21:07:05 GMT Raw View
Dave Harris <brangdon@cix.co.uk> wrote:
[...]
: However, I think it is worth having some syntactic sugar to deal with the
: simple cases, *in addition* to typeof/whatever. I am not a teacher, but I
: would hope something like "auto" could be taught on day 1 of a C++ course,
: and used very frequently. "Typeof" would be left to day 21 :-)
: Could some real teachers comment on this? Would you teach "auto" before
: "int"?
Yes.
IIRC, it was Dykstra who said that the key to good proramming is a
"separation of concerns." Students should be concerned about the
types of their data, but no more often than necessary. IMHO, it is
distracting and intrusive for computers to administer impromptu
quizzes regarding the type of a declared variables when that
information is available in the initializer.
Tom Payne
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Wed, 20 Feb 2002 15:12:06 GMT Raw View
Dave Harris wrote:
>
> igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
> > It's easy to hide the nature of such declaration in a macro
> >
> > #define Auto template<typename T_19253 > T_19253
> >
> > and use it: Auto x = ...; You can also define Auto_ref, Auto_constref,
> > etc. to your taste.
>
> True, but I am not a big fan of macros.
The point here is: the functionality of 'auto' can be achieved with
template-like declaration (an implementation may use reserved
__identifier instead of T_???). But not all of the template declarations
can be simulated with a signle 'auto' keyword. Choosing between one tool
and another tool more flexible/powerfull I'll choose the latter. The
macro above is just a syntax sugar to make this tool look simplier. If
we had typeof and template syntax, the need for a new 'auto' keyword
would be eliminated.
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Wed, 20 Feb 2002 15:38:45 GMT Raw View
Igor A. Goussarov wrote:
>Emily Winch wrote:
>>
>> If a function is written
>>
>> template< ... >
>> auto foo(... );
>>
>> The contracted interface is then "This function returns an object of some
>> type or other".
>
> But this gives absolutely no information about the return type. It
>isn't necessarily an object, it might be a builtin type or even a void.
>So this declaration actually declare nothing useful. The whole point of
>declaration is to provide a compiler with some information required to
>check function call syntax, choose the proper overloaded operator (if
>the result of this function is used as an argument to one) and call this
>function without seeing its body. And I can see how 'auto' breaks this
>concept, because now such declaration doesn't allow a compiler to
>perform overload resolution. Even if no overload resolution is required,
>it doesn't allow to perform a function call because it's not clear how
>to treat (i.e. destruct) the returned temporary.
The compiler _knows_ what the return type is. It works it out. Only the user
needs to be unaware of the return type. All the user needs to know is
the constraints on that return type: which are documented by the author
just the same as constraints on return values.
No, auto doesn't work if the compiler can't see the function body. I don't
see why that is a problem.
>> This syntax is only of any use for function templates where the return
type
>> depends on the template parameters, and only then where the template is
>> not exported or explicitly instantiated. However, in this limited case,
the
>> return statement is never far from the function declaration.
>
> Yes, it's quite common to define templated function right where it is
>declared. However the use of 'auto' here will _force_ you to do so.
Why is that a problem? At the moment, the lack of "auto" is forcing me
to effectively duplicate the code in the function to provide code to
calculate the return type. That duplicated code has to be visible to the
compiler anyway for the compiler to work out the return type. For me,
having only _one_ function which must be visible to the compiler is
better than having two nearly identical functions, one of which must be
visible to the compiler.
> A function may have several return statements. Probably with
>expressions of different types (e.g. it return either a pointer to
>object or NULL). This would be a challenge for a compiler to guess the
>correct return type. More important, it would be a challenge for the
Yep. At the moment I like the idea that multiple returns must return
the same type (exactly) or cause a compiler error. Otherwise, the
compiler just has to do the same as with the ? : operator.
>programmer to scan the source code (possibly lots of, if the function in
>question call some other functions) to figure out what the return type
>of this function is. Automatic return type deduction may incorrectly
This problem is _already there_. The code I need to simplify looks like this
template<typename T, int I>
typedef typename get_foo_return_type<T, I>::type
foo(T t){
// etc
}
If the user really wants to know the type they have to wade through
get_foo_return_type which looks pretty much the same as foo().
In any case there is _no reason_ for the user to know the type. This is
why they're calling the function: to find out! All they need to know is the
constraints on that type, which ought to be documented in the same way
as constraints on a return value.
>treat programmer's errors if he had used incompatible types in several
>return statements.
Yes.
> There is a radical solution: introduce the variant type (and name it
>'auto'). But the variant type will likely come with run-time type
>checking and casting, which contradicts with the spitit of template
>types: the latter is substituted at compile time and doesn't involve
>runtime costs. So I don't suppose we need a variant type just to avoid a
>lengthy function declarations. (Though, variant type probably have its
>application). If we agree on this, then the return type should be fixed
>and should be defined explicitly.
I already have the choice between unpleasant auto workarounds and
using a variant type. Since I know the return type at compile time I'm
using the unpleasant workarounds.
>> > To put it short: I don't see a use for any form of 'auto'
>> >(template-style or a new keyword) in function declarations.
>>
>> This is the code I'm using to work out the return types of one function,
in
>> its
>> const and non-const incarnations (13 lines each).
>
> I see. After all, how many times do you have to type the function
>return type? Probably twice: at the point of declaration and at the
>point of definition. Or once if you've typedefed it. I think we can
>afford typing the type ( :-) ) once. 'auto' in declaration of local
>variables will save us much more typing. Of course, I agree that 13
>lines is too much, but nevertheless I think that the return type should
>be declared explicitly.
1. I have to write this enormous quantity of return-type-calculating code.
2. I have to debug it.
3. I have to change it every time I change the function itself, and debug
it again.
What does the explicit return type give us that is worth all this?
Why is "auto" any worse than
"typedef typename get_foo_return_type<T, I>::type"?
>> Furthermore, people _using_ this code could quit typing
>>
>> typename iterator_type<foo>::type a = x.y<foo>();
>>
>> and type
>>
>> auto a = x.y<foo>;
>>
>> With the bonus that they no longer have to look up in my documentation
>> that "typename iterator_type<foo>::type" is the way to work out the
>> return type of the function.
>
> That's the point! In your example the return type is used twice:
>first time in a fucntion declaration and the second time in the
>definition of a local variable. There are cases when you want your local
>variable type to match its initializer type exactly. But you don't have
>to make automatic _both_ function return type (used as initializer) and
>local var type. It would be enough to leave the function type fixed and
>let the compiler guess the type of local variable.
OK.
> As for the syntax of this automatic deduction, I've seen three
>options:
>1. 'auto' keyword
>2. template-like declaration
>3. typeof operator.
> Choosing between the first two, I admit that template approach is
>more powerful. 'auto' keyword can be simulated with macro "#define auto
>template <typename __t> __t", but I don't see how a single 'auto'
>keyword can cover all the variety of template declarations. One
>particular example where the use of 'auto' is impossible is when the
>initializer is either an array initializer or a string literal. Given
>
>auto x = "abc";
>
>what should a compiler guess:
>
>char x[] = "abc";
>const char* x = "abc";
>const char (&x)[] = "abc"; ?
The compiler guesses the actual type of "abc".
>If we use template syntax, then the standard rules of type parameter
>deduction take place and the type deduced is "const char*". If the
>programmer want another meaning, he can use "template <typename __t>
>const __t&" or similar. Template approach lets you create as many macros
>(auto, auto_ref, auto_constref, ...) as you want. 'auto' keyword can
>have more power if it was treated like a template-deduced type
>parameter. Then one will be able to use
>
>const auto& x = "abc";
>map<auto, auto>& y = myMap; // here both auto are independent.
>
>But don't you think that it's getting closer to the template semantics?
>If so then using template syntax here is more consistent.
Template semantics are used to introduce a type which can be provided
by the user of the code. auto semantics would be used to provide a type
which is provided by the author of the code. I think conflating the two
is confusing.
> As for the typeof operator, since it can be used not only in variable
>declaration but in any other place where a type name is expected (e.g.
>new typeof(...)), I don't see it as an alternative to the first two
>options. Using typeof for automatic type deduction doesn't make things
>easier because the initializer expression must be repeated twice.
> Having said this, I would like to see both typeof keyword both
>template-like automatic variable declarations in the language.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Wed, 20 Feb 2002 22:40:31 GMT Raw View
Emily Winch wrote:
>
> The compiler _knows_ what the return type is. It works it out. Only the user
> needs to be unaware of the return type. All the user needs to know is
> the constraints on that return type: which are documented by the author
> just the same as constraints on return values.
The _user_ would be unaware of function return type: declarations
like "auto x = YourClass<int>::foo<double>(5);" effectively hides the
type of initializer expression from the user (And this is a good place
to use 'auto').
This is the _author_ of the aforementioned function who must be aware of
the return type. And enforcing this return type in the code is IMHO
better then documenting it in a separate file.
> > A function may have several return statements. Probably with
> >expressions of different types (e.g. it return either a pointer to
> >object or NULL). This would be a challenge for a compiler to guess the
> >correct return type. More important, it would be a challenge for the
>
> Yep. At the moment I like the idea that multiple returns must return
> the same type (exactly) or cause a compiler error. Otherwise, the
> compiler just has to do the same as with the ? : operator.
Returning exactly the same type will sometimes require an explicit
cast. This means you have to put that long type not in the function
declaration, but in a cast expression in the return statement. What's
the gain then?
> 1. I have to write this enormous quantity of return-type-calculating code.
> 2. I have to debug it.
> 3. I have to change it every time I change the function itself, and debug
> it again.
>
> What does the explicit return type give us that is worth all this?
> Why is "auto" any worse than
> "typedef typename get_foo_return_type<T, I>::type"?
Explicit return type:
1. Makes the compilation straightforward (and thus faster and less
error-prone). No need to guess the return type. Consider
auto f(int x)
{
if (x == 0) return 1;
return f(x - 1) * x;
}
Here the return type of f() is self-dependent. Can you describe the
algorithm which will resolve it correctly? What if there is a
user-defined type Bug which has a constructor Bug(int) and
Bug::operator*(int)? Should the compiler iterate through all known types
to find such buggy possibility?
2. Catches programming errors if the return expression does not match
the desired return type.
3. Saves you some typing: you've said that you want all return statement
expressions to be of the same type. The sometimes you'll need an
explicit cast or an explicit temporary construction (like "return
(T*)NULL;", "return MyClass(1);" ). This way you'll have to repeat the
return type as many times nearly as many return statements you have.
4. Lets you employ implicit conversion from return expression to the
return type.
'auto' as a function return type has a very limited application:
1. the function should be defined at the point of declaration.
2. it should not be recursive (directly or indirectly)
> >auto x = "abc";
> >
> >what should a compiler guess:
> >
> >char x[] = "abc";
> >const char* x = "abc";
> >const char (&x)[] = "abc"; ?
>
> The compiler guesses the actual type of "abc".
I.e. const char[4]? It's not always what I want. And it's plain wrong
for array initializer because if
int x[5];
auto y = x;
is treated like "int y[5] = x;" then this line is ill-formed.
> >const auto& x = "abc";
> >map<auto, auto>& y = myMap; // here both auto are independent.
> >
> >But don't you think that it's getting closer to the template semantics?
> >If so then using template syntax here is more consistent.
>
> Template semantics are used to introduce a type which can be provided
> by the user of the code. auto semantics would be used to provide a type
> which is provided by the author of the code. I think conflating the two
> is confusing.
Sorry, I haven't made myself clear. I meant "it's getting closer to
the template function type parameter deduction semantics".
Igor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 20 Feb 2002 22:40:19 GMT Raw View
igusarov@akella.com (Igor A. Goussarov) wrote (abridged):
> The point here is: the functionality of 'auto' can be achieved with
> template-like declaration (an implementation may use reserved
> __identifier instead of T_???). But not all of the template declarations
> can be simulated with a signle 'auto' keyword.
I agree with all that.
> Choosing between one tool and another tool more flexible/powerfull
> I'll choose the latter.
I have been arguing against having to make that choice. I want both auto
and typeof. Typeof for power, auto for simplicity. Typeof for experts,
auto for novices.
> The macro above is just a syntax sugar to make this tool look
> simplier. If we had typeof and template syntax, the need for a
> new 'auto' keyword would be eliminated.
Perhaps we disagree about the value of syntactic sugar. I think it is
important.
Or perhaps we disagree about macros. Are you suggesting that #define Auto
be added to the standard library, so that we have to #include <Auto>
before we can use it? I think this will lead to the same kind of problems
we already see with NULL. People will forget to #include it, and their
code will still compile because they do #include <vector> and vector uses
Auto. And then their code will break when they go to a different vendor
whose vector does not use Auto.
Even if they do remember to include it, we have condemned every C++ file
in the world, for ever more, to start with #include <Auto>. Either that or
risk Auto not being available when we want to use it. The complexity is
hardly worth it for the simple cases which Auto is intended to help.
If the Auto is not even standard, the problems get worse. We will get
myriad different spellings of it and its header. It is a bit like
#define BEGIN {, where people invent their own incompatible little
languages. Auto will belong to C++ dialects.
Macros don't respect namespaces, so making Auto a macro, whether de facto
standard or actual standard, has hardly any advantage over making it a
proper keyword.
C++0x should be easier to teach and easier to use than current C++.
Leaving out auto, or making it a macro, will not help that aim.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Wed, 13 Feb 2002 15:47:47 GMT Raw View
The best suggestion I've heard so far is:
template <class T> T x = ... ;
which would also admit:
template <class T> T const* p = ... ;
template <class T, class U> T const& (*f)(U**) = ... ;
etc.
And it doesn't require any new keywords :)
"John Nagle" <nagle@animats.com> wrote in message
news:3C68A05C.7000002@animats.com...
> There were some proposals to add implicit type declaration
> in initialization to the language, so that one could write
>
> let x = y; // x is declared as the type of x
>
> or, more usefully
>
> for (let p=a.begin(); p!= a.end(); p++) {...}
>
> instead of the rather bulky iterator declaration syntax
> currently required.
>
> The "auto" keyword was also suggested for this role.
>
> What's the status of that proposal? I consider it a
> reasonably good idea. We could probably tolerate
> "let" as a keyword; it's not a popular variable name.
>
> John Nagle
> Animats
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Julian Smith <jules@op59.net>
Date: Wed, 13 Feb 2002 16:18:48 GMT Raw View
David Abrahams wrote:
>
> The best suggestion I've heard so far is:
>
> template <class T> T x = ... ;
>
> which would also admit:
>
> template <class T> T const* p = ... ;
> template <class T, class U> T const& (*f)(U**) = ... ;
Not bad, but I'd prefer Stroustrup's alternative declaration syntax
(described in D&E), which looks like:
main: ( argv: -> -> char, argc: int) int {...}
p: -> const int;
f: ->( : ->-> int) & const double = ...;
Implicit typing is then just a matter of ommiting the type information:
f: = ...
- Julian
--
http://www.op59.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Wed, 13 Feb 2002 17:44:11 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> said:
> The best suggestion I've heard so far is:
>
> template <class T> T x = ... ;
>
> which would also admit:
>
> template <class T> T const* p = ... ;
> template <class T, class U> T const& (*f)(U**) = ... ;
>
> etc.
>
> And it doesn't require any new keywords :)
That doesn't extend too well to doing this:
template<class T, int I>
template<class Ret> Ret foo() {
return /* something whose type depends on T and I */ ;
}
Which is the same phenomenon as what you're discussing, so it should really
look the same, and I'd argue that this feature is nearly as important.
Emily.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Wed, 13 Feb 2002 22:03:12 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote:
> The best suggestion I've heard so far is:
>
> template <class T> T x = ... ;
>
> which would also admit:
>
> template <class T> T const* p = ... ;
> template <class T, class U> T const& (*f)(U**) = ... ;
>
> etc.
>
> And it doesn't require any new keywords :)
OTOH, it breaks the existing syntactical concept that
"template<...>" introduces a parameterized declaration.
Your proposed syntax matches another extension I've
toyed with: object templates. I.e., after your first
declaration, I would expect to be able to refer to an
object "x<int>" (of type int).
(A matter of taste of course.)
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Wed, 13 Feb 2002 21:34:13 CST Raw View
I think we're getting too complicated here.
I kind of liked the "let" idea, as a simplification.
John Nagle
Animats
Daveed Vandevoorde wrote:
> "David Abrahams" <david.abrahams@rcn.com> wrote:
....object templates...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Thu, 14 Feb 2002 15:46:00 GMT Raw View
"Daveed Vandevoorde" <google@vandevoorde.com> wrote in message
news:52f2f9cd.0202131157.5652aa30@posting.google.com...
> "David Abrahams" <david.abrahams@rcn.com> wrote:
> > The best suggestion I've heard so far is:
> >
> > template <class T> T x = ... ;
> >
> > which would also admit:
> >
> > template <class T> T const* p = ... ;
> > template <class T, class U> T const& (*f)(U**) = ... ;
> >
> > etc.
> >
> > And it doesn't require any new keywords :)
>
> OTOH, it breaks the existing syntactical concept that
> "template<...>" introduces a parameterized declaration.
So few "syntactical concepts" make any intuitable sense in C++ that I'm not
too worried about that.
> Your proposed syntax matches another extension I've
> toyed with: object templates. I.e., after your first
> declaration, I would expect to be able to refer to an
> object "x<int>" (of type int).
>
> (A matter of taste of course.)
I'm not sure. What's the initialization order of instantiations of x<T>? It
seems to present a few problems and it doesn't solve any that I've had. It
also seems to be incompatible with mmy intended meaning (deduced type in
declaration). Does it solve some real-world problem you've encountered?
-Dave(!ed)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Thu, 14 Feb 2002 15:56:11 GMT Raw View
"Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
news:a4e3vp$f6i$1@reader0.news.uk.quza.net...
>
> "David Abrahams" <david.abrahams@rcn.com> said:
>
> > The best suggestion I've heard so far is:
> >
> > template <class T> T x = ... ;
> >
>
> That doesn't extend too well to doing this:
>
> template<class T, int I>
> template<class Ret> Ret foo() {
> return /* something whose type depends on T and I */ ;
> }
>
> Which is the same phenomenon as what you're discussing, so it should
really
> look the same, and I'd argue that this feature is nearly as important.
Hi Emily,
I almost agree with everything you're saying here, but...
1. Why do you say "it doesn't extend well"? It seems you've just done it (I
might not use a separate template<...> incantation, but that's just a
detail).
2. Isn't there a bigger problem here because now callers can't deduce the
return type given just a declaration?
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Emily Winch" <usenet@blueumbrella.NOSPAM.net>
Date: Thu, 14 Feb 2002 17:10:25 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> said
> "Emily Winch" <usenet@blueumbrella.NOSPAM.net> wrote in message
> news:a4e3vp$f6i$1@reader0.news.uk.quza.net...
> >
> > "David Abrahams" <david.abrahams@rcn.com> said:
> >
> > > The best suggestion I've heard so far is:
> > >
> > > template <class T> T x = ... ;
> > >
> >
> > That doesn't extend too well to doing this:
> >
> > template<class T, int I>
> > template<class Ret> Ret foo() {
> > return /* something whose type depends on T and I */ ;
> > }
> >
> > Which is the same phenomenon as what you're discussing, so it should
> really
> > look the same, and I'd argue that this feature is nearly as important.
>
> Hi Emily,
>
> I almost agree with everything you're saying here, but...
>
> 1. Why do you say "it doesn't extend well"? It seems you've just done it
(I
> might not use a separate template<...> incantation, but that's just a
> detail).
It seems a bit hairy, the way that something like (contrived example ahead)
template<typename T, typename U>
U foo(T t){
U u; // deduce that if you can!!!
u.stuff(t);
return u;
}
has different usage from
template<typename T, typename U>
U foo(T t){
typedef typename T::template long_calculation<I>::type return_type;
return return_type(t.stuff());
}
Even though the declarations would look the same.
OK, so using
template<typename T>
template<typename U>
U foo(T t);
like I did would disambiguate it, but it would still seem weird: the user
has to remember to specify T if it isn't deducible from the parameter list,
but not U.
Not to mention the ick factor of:
template<typename T>
template<typename U>
template<typename V>
V foo<T>::bar<U>() { /* */ }
> 2. Isn't there a bigger problem here because now callers can't deduce the
> return type given just a declaration?
Mostly the callers can write
auto T t = foo< /* whatever */ >();
But if they need more than that, maybe they could write
typeof(foo< /* whatever */ >()) t;
Emily
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: Tue, 12 Feb 2002 15:53:14 GMT Raw View
There were some proposals to add implicit type declaration
in initialization to the language, so that one could write
let x = y; // x is declared as the type of x
or, more usefully
for (let p=a.begin(); p!= a.end(); p++) {...}
instead of the rather bulky iterator declaration syntax
currently required.
The "auto" keyword was also suggested for this role.
What's the status of that proposal? I consider it a
reasonably good idea. We could probably tolerate
"let" as a keyword; it's not a popular variable name.
John Nagle
Animats
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Wed, 13 Feb 2002 00:02:11 GMT Raw View
John Nagle <nagle@animats.com> writes:
[...]
| We could probably tolerate
| "let" as a keyword; it's not a popular variable name.
How is that?
(I've already use "let" as a function name in my own library
implementation of Scheme)
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Tue, 12 Feb 2002 19:04:32 CST Raw View
John Nagle <nagle@animats.com> wrote in message news:<3C68A05C.7000002@animats.com>...
> There were some proposals to add implicit type declaration
> in initialization to the language, so that one could write
>
> let x = y; // x is declared as the type of x
>
> or, more usefully
>
> for (let p=a.begin(); p!= a.end(); p++) {...}
>
> instead of the rather bulky iterator declaration syntax
> currently required.
>
> The "auto" keyword was also suggested for this role.
>
> What's the status of that proposal? I consider it a
> reasonably good idea. We could probably tolerate
> "let" as a keyword; it's not a popular variable name.
I seem to remember that this was brought up in a sort of
"bainstorm session" about potential C++ extensions among
J16 members. As I recall a keyword "dcl" (instead of
"let") was also mentioned.
I don't think there has been a formal proposal for an
extension yet.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]