Topic: Extension for C++0x: Overload on ICEs
Author: d.frey@gmx.de (Daniel Frey)
Date: Tue, 27 Jan 2004 04:17:54 +0000 (UTC) Raw View
On Mon, 26 Jan 2004 02:11:27 +0100, Douglas Gregor wrote:
> Daniel Frey wrote:
>
>> Douglas Gregor wrote:
>>> Daniel Frey wrote:
>>>
>>>>Each ICE parameter is removed from the template-parameter list
>>>>internally, the function parameter is turned into an internal type
>>>>__ice<int> instead of int. If no template parameters are left, the
>>>>function is, conceptually, no longer a template function! This allows
>>>>the compiler to prefer #2 over #1, although #2 looks like a template
>>>>function and #1 is already an "exact" match given the current rules.
>>>>The third overload also needs to be placed into the type. After the
>>>>replacements, the compiler sees:
>>>>
>>>>void f( int i ); // #1
>>>>void f( __ice<int> I ); // #2
>>>>void f( __ice_value<2> ); // #3
>>>>
>>>>I hope you get the idea. As I am not a compiler writer, so if some of
>>>>them are reading this, I'd like to from them whether the above sounds
>>>>feasible.
>>>
>>> I don't believe those overload resolution rules will work the way we
>>> want. Consider the following, where after substituting a value for N
>>> both are still templates:
>>>
>>> template<typename T, int N> T pow(T x, N) template<typename T> T
>>> pow(T x, int N);
>>
>> I don't see a problem here, but I came to the conclusion that using the
>> template<>-syntax is very misleading and doesn't reflect what we
>> actually want. See below..
>
> According to the overload rules you've mentioned (as I understand them),
> the call pow(3.14, 2) would be ambiguous, because #1 remains a template
> function after substitution of 2 for N as does #2. How do we order
> between #1 and #2, if both are templates and there are no new matching
> categories?
First of all, consider:
template< typename T > void f( const T&, int );
template< typename T > void f( const T&, double );
f( 42, 42 );
I guess we don't disagree that the first function is called here, right?
If you disagree, I'm at a loss as to what you mean... :)
And I actually want a new matching category, although the first syntax I
suggested is quite misleading. The second syntax I proposed was actually
meant to communicate that more directly as it should remove the problems
that arise from the use of a template-parameter and the
template-matching-rules.
I just thought about the naming once more and I think there is a nice
modification for the second syntax:
void f( static const int i ); #1
void f( int i ); #2
(We don't need the ability to specialize #1 directly, thanks Jonathan for
this enlightment. I was initially concerned about loosing the ability of
specifying different return types for the specializations, but this can
obviously be added anyway through the normal language)
For the naming: I choose "static const int" over "template int" or
something because it matches:
class X {
static const int i = 42;
};
OK, now for the new matching category. We have something which is called
an "integral constant expression". The question is: How is this type
actually called in C++? "int" clearly isn't descriptive enough. What we
need is some explicitly spelled out type for "integral constant
expression", which I suggest is "static const int". Besides the discussion
of the name, I think we mean pretty much the same: An ICE matches this
type better than "int". That way, it should be easy to understand which
overload is choosen - with or without template parameters involved. They
just behave like they always do and as I showed in the above example of
f(42,42).
> Note that #2 is implicitly a template, but has no template header. IIRC,
> when this same thing came up in the auto/decltype/typeof discussions, it
> was not generally liked.
Nope, I won't consider it a template. This is exactly what makes the
extension hard to understand if you treat the new matching rank as a
template parameter.
> I don't care much about the syntax, but any syntax along these lines:
>
> template<int N, typename T> T pow(T x, keyword_opt N);
>
> makes it easier to write portable code. For instance, assume we get this
> feature for C++0x and consider the pow example:
>
> template<int N, typename T> T pow(T x, keyword_opt N); // #1a: on
template< typename T > T pow(T x, static const int N); #1c
> C++0x template<int N, typename T> T pow(T x); // #1b: on C++98/03
> template<typename T> T pow(T x, int n); // #2
>
> The expression pow(x, n) will work on C++98/03 and C++0x; on C++0x, when
> n is an integral constant expression, we get the (faster?) template
> version.
>
> The expression pow<N>(x) will work on C++98/03 and C++0x, and have the
> same behavior on both.
I don't see why #1c shouldn't provide the same expressiveness as #1a.
>> The used keyword "template" is of course only one possibility, we could
>> also think about "static" (once again a new meaning for static ;)) or
>> some completely new keyword like "integral" or "[you-name-it]".
>
> In the syntactic style I'm advocating, we don't actually need any
> keyword (or even the type): it's part of the template header because
> we're defining a function template. When Aleksey and I were discussing
> this, we decided to use the keyword "template" (as you have), but only
> because we had to bash it into GCC's old YACC-based parser without too
> much fuss :)
Again, I think that this is actually the biggest problem with the "old
proposal" (no offense intended): Don't think of it a template parameter!
When I finally had the idea to make it a "normal type" instead of using
template parameters, I finally felt that this is a relieve. Things become
so much easier and cleaner then... but then... YMMV :))
Regards, Daniel
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: gregod@cs.rpi.edu (Douglas Gregor)
Date: Mon, 26 Jan 2004 01:11:27 +0000 (UTC) Raw View
Daniel Frey wrote:
> Douglas Gregor wrote:
>> Daniel Frey wrote:
>>
>>>Each ICE parameter is removed from the template-parameter list
>>>internally, the function parameter is turned into an internal type
>>>__ice<int> instead of int. If no template parameters are left, the
>>>function is, conceptually, no longer a template function! This allows
>>>the compiler to prefer #2 over #1, although #2 looks like a template
>>>function and #1 is already an "exact" match given the current rules. The
>>>third overload also needs to be placed into the type. After the
>>>replacements, the compiler sees:
>>>
>>>void f( int i ); // #1
>>>void f( __ice<int> I ); // #2
>>>void f( __ice_value<2> ); // #3
>>>
>>>I hope you get the idea. As I am not a compiler writer, so if some of
>>>them are reading this, I'd like to from them whether the above sounds
>>>feasible.
>>
>>
>> I don't believe those overload resolution rules will work the way we
>> want. Consider the following, where after substituting a value for N both
>> are still templates:
>>
>> template<typename T, int N> T pow(T x, N)
>> template<typename T> T pow(T x, int N);
>
> I don't see a problem here, but I came to the conclusion that using the
> template<>-syntax is very misleading and doesn't reflect what we
> actually want. See below..
According to the overload rules you've mentioned (as I understand them), the
call pow(3.14, 2) would be ambiguous, because #1 remains a template
function after substitution of 2 for N as does #2. How do we order between
#1 and #2, if both are templates and there are no new matching categories?
> I think that this also reflects what should really happen: We need a new
> type attribute which notes that it's an integral constant expression. I
> thus think that something like this is closer to what we want than my
> initially proposed syntax:
>
> void f( int i = 0 ); // #1
> void f( template int I ); // #2, I is an ICE
> void f( template int 0 ); // #3, specialize #2 for 0
>
> int main() {
> const int i = 0;
> f( 0 ); // calls #3
> f( 1 ); // calls #2
> f( i ); // calls #1
> f(); // calls #3
> }
>
> The signature can now also include the template in the argument type as
> well as the value itself for specializations. I think that it's ways
> clearer to see and think about the overloading rules with the above
> syntax than with the old approach. What do you think?
Note that #2 is implicitly a template, but has no template header. IIRC,
when this same thing came up in the auto/decltype/typeof discussions, it
was not generally liked.
I don't care much about the syntax, but any syntax along these lines:
template<int N, typename T> T pow(T x, keyword_opt N);
makes it easier to write portable code. For instance, assume we get this
feature for C++0x and consider the pow example:
template<int N, typename T> T pow(T x, keyword_opt N); // #1a: on C++0x
template<int N, typename T> T pow(T x); // #1b: on C++98/03
template<typename T> T pow(T x, int n); // #2
The expression pow(x, n) will work on C++98/03 and C++0x; on C++0x, when n
is an integral constant expression, we get the (faster?) template version.
The expression pow<N>(x) will work on C++98/03 and C++0x, and have the same
behavior on both.
> The used keyword "template" is of course only one possibility, we could
> also think about "static" (once again a new meaning for static ;)) or
> some completely new keyword like "integral" or "[you-name-it]".
In the syntactic style I'm advocating, we don't actually need any keyword
(or even the type): it's part of the template header because we're defining
a function template. When Aleksey and I were discussing this, we decided to
use the keyword "template" (as you have), but only because we had to bash
it into GCC's old YACC-based parser without too much fuss :)
Doug
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Mon, 12 Jan 2004 15:35:39 +0000 (UTC) Raw View
Hello, world!
I'd like to propose an extension of C++ to be able to overload a
function for integral constant expressions (ICEs). The proposed syntax is=
:
void f( int i ) // #1
{
// Used if f is called with a non-ICE
}
template< int I > void f( const int I ) // #2
{
// Used if f is called with an ICE !=3D 2
}
template<> void f<2>( const int ) // #3
{
// Specialized if f is called with an ICE =3D=3D 2
}
int main()
{
const int i =3D 2;
f(i); // calls #1
f(1); // calls #2
f(2); // calls #3
}
As #2 is currently illegal, this extension won't break any existing code
AFAICS. It allows several things which are today hard or impossible to
achieve:
a) Optimizations, think of pow(x,2). Today, all you can to is a run-time
check for pow's second parameter of request the user to use a different
syntax like pow<2>(x).
b) You can propagate the information from the ICE to the return type,
important for meta-programming, e.g. it might be of use in a
dimension/unit-library.
c) For some types, like a 'money'-class, you might want to be able to
compare to an ICE 0, but not to any other integers. Consider:
money m( 42, "EUR" );
if( m > 0 ) {} // OK
if( m > 40 ) {} // Should not compile. 40 doesn't have a unit
if( m > money( 40, "USD" ) ) {} // OK as $40 can be converted now
d) Expressions like sqrt(2) could now be detected as a constant and=20
won't lead to inexact and inefficient run-time calculation, giving a=20
more natural syntax than sqrt_two sqrt(two), sqrt2 or whatever.
One of the problems that this extension probably has is, that the=20
lookup-rules for overloads become yet again more complicated. And they=20
are already complex enough, aren't they? :o)
I'd like to hear opinions about whether others think that it makes sense
and if you can see any problems with it. If there is enough interest,
I'd like to try making it an official proposal for C++0x (and help on
that is appreciated, so if you are interested... :)
Regards, Daniel
--=20
Daniel Frey
aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 13 Jan 2004 19:15:23 +0000 (UTC) Raw View
daniel.frey@aixigo.de (Daniel Frey) writes:
> Hello, world!
>
> I'd like to propose an extension of C++ to be able to overload a
> function for integral constant expressions (ICEs). The proposed syntax is:
>
> void f( int i ) // #1
> {
> // Used if f is called with a non-ICE
> }
>
> template< int I > void f( const int I ) // #2
> {
> // Used if f is called with an ICE != 2
> }
>
> template<> void f<2>( const int ) // #3
> {
> // Specialized if f is called with an ICE == 2
> }
Generally, and perhaps more importantly, this should be supported:
template<class T, T x>
void f(T x)
{ ... }
It would apply to any constant expression including function pointers
and references, pointers to data members, etc.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.jamesd.demon.co.uk/csc/faq.html ]
Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Wed, 14 Jan 2004 17:02:59 +0000 (UTC) Raw View
David Abrahams wrote:
> daniel.frey@aixigo.de (Daniel Frey) writes:
>=20
>>I'd like to propose an extension of C++ to be able to overload a
>>function for integral constant expressions (ICEs). The proposed syntax =
is:
>>
>>void f( int i ) // #1
>>{
>> // Used if f is called with a non-ICE
>>}
>>
>>template< int I > void f( const int I ) // #2
>>{
>> // Used if f is called with an ICE !=3D 2
>>}
>>
>>template<> void f<2>( const int ) // #3
>>{
>> // Specialized if f is called with an ICE =3D=3D 2
>>}
>=20
> Generally, and perhaps more importantly, this should be supported:
>=20
> template<class T, T x>=20
> void f(T x)
> { ... }
>=20
> It would apply to any constant expression including function pointers
> and references, pointers to data members, etc.
Looks like a good idea. Although I wonder how the specialization should=20
look like. And I guess we have to write down the overload rules, which=20
could be quite complicate. For my proposal, the idea is the following:
Each ICE parameter is removed from the template-parameter list=20
internally, the function parameter is turned into an internal type=20
__ice<int> instead of int. If no template parameters are left, the=20
function is, conceptually, no longer a template function! This allows=20
the compiler to prefer #2 over #1, although #2 looks like a template=20
function and #1 is already an "exact" match given the current rules. The=20
third overload also needs to be placed into the type. After the=20
replacements, the compiler sees:
void f( int i ); // #1
void f( __ice<int> I ); // #2
void f( __ice_value<2> ); // #3
I hope you get the idea. As I am not a compiler writer, so if some of=20
them are reading this, I'd like to from them whether the above sounds=20
feasible.
For your more general approach, I'm at a loss to formulate something=20
appropriate, but maybe you can envision some nice rules how to handle it=20
and share them with us :)
Regards, Daniel
--=20
Daniel Frey
aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: gregod@cs.rpi.edu (Douglas Gregor)
Date: Fri, 16 Jan 2004 15:38:30 +0000 (UTC) Raw View
Daniel Frey wrote:
> Hello, world!
>
> I'd like to propose an extension of C++ to be able to overload a
> function for integral constant expressions (ICEs). The proposed syntax is:
[snip]
> I'd like to hear opinions about whether others think that it makes sense
> and if you can see any problems with it. If there is enough interest,
> I'd like to try making it an official proposal for C++0x (and help on
> that is appreciated, so if you are interested... :)
Please do!
Aleksey Gurtovoy suggested this about two years ago, in the context of
making Boost's bind and mem_fn more efficient:
http://groups.yahoo.com/group/boost/message/24271
We discussed it further and hacked up an implementation in GCC, but never
got around to writing a proposal for it :(. I'll be happy to share ideas,
review a proposal, etc., but currently I can't dedicate enough time to
write a proposal myself.
Doug
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: gregod@cs.rpi.edu (Douglas Gregor)
Date: Fri, 16 Jan 2004 16:09:06 +0000 (UTC) Raw View
Daniel Frey wrote:
> Looks like a good idea. Although I wonder how the specialization should
> look like. And I guess we have to write down the overload rules, which
> could be quite complicate. For my proposal, the idea is the following:
>
> Each ICE parameter is removed from the template-parameter list
> internally, the function parameter is turned into an internal type
> __ice<int> instead of int. If no template parameters are left, the
> function is, conceptually, no longer a template function! This allows
> the compiler to prefer #2 over #1, although #2 looks like a template
> function and #1 is already an "exact" match given the current rules. The
> third overload also needs to be placed into the type. After the
> replacements, the compiler sees:
>
> void f( int i ); // #1
> void f( __ice<int> I ); // #2
> void f( __ice_value<2> ); // #3
>
> I hope you get the idea. As I am not a compiler writer, so if some of
> them are reading this, I'd like to from them whether the above sounds
> feasible.
I don't believe those overload resolution rules will work the way we want.
Consider the following, where after substituting a value for N both are
still templates:
template<typename T, int N> T pow(T x, N)
template<typename T> T pow(T x, int N);
I think the right answer is to introduce another match ranking, "template
match" or "integral constant expression match", that is better than an
exact match. The actual change to the overloading rules is quite minimal.
We did prototype this ordering method in GCC, and it was both easy and
intuitive.
The biggest hurdle we faced was to determine what the type of such a
function would be. We need the integral constants to be in the function
signature for template argument deduction and for overloading, but these
integral constants are never actually passed. The big question: what is the
type of &pow<double, 17>?
We decided that the type is T (*)(T). The integral constants---which are
never passed on the stack---are completely removed from the type of the
function. This way, the function type matches the way the function is
called (very important!). We also don't need to be concerned with types
like __ice<int> and __ice_value<int,2> being exposed to the user, and
having to be synthesized so that someone can call &pow<5> through the
function pointer, e.g.,
transform(values.begin(), values.end(), back_inserter(squared),
&pow<5>);
Doug
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Tue, 20 Jan 2004 03:07:15 +0000 (UTC) Raw View
Douglas Gregor wrote:
> Daniel Frey wrote:
>=20
>>Each ICE parameter is removed from the template-parameter list
>>internally, the function parameter is turned into an internal type
>>__ice<int> instead of int. If no template parameters are left, the
>>function is, conceptually, no longer a template function! This allows
>>the compiler to prefer #2 over #1, although #2 looks like a template
>>function and #1 is already an "exact" match given the current rules. Th=
e
>>third overload also needs to be placed into the type. After the
>>replacements, the compiler sees:
>>
>>void f( int i ); // #1
>>void f( __ice<int> I ); // #2
>>void f( __ice_value<2> ); // #3
>>
>>I hope you get the idea. As I am not a compiler writer, so if some of
>>them are reading this, I'd like to from them whether the above sounds
>>feasible.
>=20
>=20
> I don't believe those overload resolution rules will work the way we wa=
nt.
> Consider the following, where after substituting a value for N both are
> still templates:
>=20
> template<typename T, int N> T pow(T x, N)
> template<typename T> T pow(T x, int N);
I don't see a problem here, but I came to the conclusion that using the=20
template<>-syntax is very misleading and doesn't reflect what we=20
actually want. See below..
> I think the right answer is to introduce another match ranking, "templa=
te
> match" or "integral constant expression match", that is better than an
> exact match. The actual change to the overloading rules is quite minima=
l.
> We did prototype this ordering method in GCC, and it was both easy and
> intuitive.
>=20
> The biggest hurdle we faced was to determine what the type of such a
> function would be. We need the integral constants to be in the function
> signature for template argument deduction and for overloading, but thes=
e
> integral constants are never actually passed. The big question: what is=
the
> type of &pow<double, 17>?
>=20
> We decided that the type is T (*)(T). The integral constants---which ar=
e
> never passed on the stack---are completely removed from the type of the
> function. This way, the function type matches the way the function is
> called (very important!). We also don't need to be concerned with types
> like __ice<int> and __ice_value<int,2> being exposed to the user, and
> having to be synthesized so that someone can call &pow<5> through the
> function pointer, e.g.,
I think that this also reflects what should really happen: We need a new=20
type attribute which notes that it's an integral constant expression. I=20
thus think that something like this is closer to what we want than my=20
initially proposed syntax:
void f( int i =3D 0 ); // #1
void f( template int I ); // #2, I is an ICE
void f( template int 0 ); // #3, specialize #2 for 0
int main() {
const int i =3D 0;
f( 0 ); // calls #3
f( 1 ); // calls #2
f( i ); // calls #1
f(); // calls #3
}
The signature can now also include the template in the argument type as=20
well as the value itself for specializations. I think that it's ways=20
clearer to see and think about the overloading rules with the above=20
syntax than with the old approach. What do you think?
The used keyword "template" is of course only one possibility, we could=20
also think about "static" (once again a new meaning for static ;)) or=20
some completely new keyword like "integral" or "[you-name-it]".
Regards, Daniel
--=20
Daniel Frey
aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Tue, 20 Jan 2004 06:43:59 +0000 (UTC) Raw View
"Daniel Frey" <daniel.frey@aixigo.de> wrote in message
news:bugg3f$i4j$1@swifty.westend.com...
>Douglas Gregor wrote:
>> Daniel Frey wrote:
>>
>I think that this also reflects what should really happen: We need a
new
>type attribute which notes that it's an integral constant expression.
I
>thus think that something like this is closer to what we want than my
>initially proposed syntax:
>
>void f( int i = 0 ); // #1
>void f( template int I ); // #2, I is an ICE
>void f( template int 0 ); // #3, specialize #2 for 0
>
>int main() {
> const int i = 0;
> f( 0 ); // calls #3
> f( 1 ); // calls #2
> f( i ); // calls #1
> f(); // calls #3
>}
>
>The signature can now also include the template in the argument type
as
>well as the value itself for specializations. I think that it's ways
>clearer to see and think about the overloading rules with the above
>syntax than with the old approach. What do you think?
>
>The used keyword "template" is of course only one possibility, we
could
>also think about "static" (once again a new meaning for static ;)) or
>some completely new keyword like "integral" or "[you-name-it]".
>
I like this a lot. I was going to suggest this several days ago, but I
was unsure what the general implications for the language would be. I
though about 'integral', 'ice' and 'intergal_contant', but I don't
like these because as David Abrahams suggested, it might be useful to
extend the technique to constant objects generally. In particular, it
could have beneficial interactions with Stroustrup's literals for
user-defined types, and Gabriel Del Reis's generalize constant
expressions. (See
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1511.pdf and
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1521.pdf.)
I think it's unnecessary to define a new specialization syntax. Within
the body of a function, a variable decalred 'template' should be
treatable as a constant expression. After all, the function will only
be instantiated once for each actual invocation with a constant
expression. If that's true, all you need is the type attribute:
template<int N>
void f_impl();
template<>
void f_impl<2>(); // Specialization for 2.
void f( int i = 0 );
void f(template int i) { f<i>(); }
The name I like best is 'static_const'. It's awkward because it
combines two existing keywords; however, it is a fairly exact
description of what's at issues: constants whose values are known
statically, i.e., at compile time. Furthermore, one of the principal
examples of intergal constant expressions are intergral data members
decalred 'static const' (and initialized in class).
The most conservative version of the proposal would only allow the
modifier on variables decalred in function argument lists, and only
for integral types. A broader proposal would allow 'static_const' on
any function argument for which constant expressions make sense. A
more radical proposal might allow static_const as a modifier for
inline (not necessarily member) functions. A static_const function
would have arguments each qualified with static_const, all variables
decalred in the function would implicitly be static_const, and all
functions called (if function calls are allowed) would have to be
static_const. These functions could then be used in constant
expressions.
As I said, I haven't considered the full implications of these idea;
the last part, in particular, may make the compiler's job too hard. I
definitely like your idea, though, and think a new type attribute is
the way to go. (BTW, I dislike 'template' here; it gives no clue
what's really going on.)
Best Regards,
Jonathan
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]
Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Wed, 21 Jan 2004 04:23:00 +0000 (UTC) Raw View
""Jonathan Turkanis"" <technews@kangaroologic.com> wrote in message:
> I think it's unnecessary to define a new specialization syntax.
Within
> the body of a function, a variable decalred 'template' should be
> treatable as a constant expression. After all, the function will
only
> be instantiated once for each actual invocation with a constant
> expression. If that's true, all you need is the type attribute:
>
> template<int N>
> void f_impl();
>
> template<>
> void f_impl<2>(); // Specialization for 2.
>
> void f( int i = 0 );
> void f(template int i) { f<i>(); }
Of course, this should say
void f(template int i) { f_impl<i>(); }
Jonathan
---
[ comp.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.jamesd.demon.co.uk/csc/faq.html ]