Topic: Conflict with allowable types for value-based template parameters
Author: dwalker07@snet.net.invalid (Daryle Walker)
Date: Mon, 18 Jun 2001 04:12:44 GMT Raw View
I was having an e-mail conversation with someone else about a plan for a
class template. We disagreed on what types are allowed to be used in
value-based (a.k.a. non-type, non-template) template parameters. The
other guy noted that the standard supports both our views, and so the
standard guys need to fix it. Here's a copy of our last correspondence.
----------
From: Hubert HOLIN <E-MAIL-REMOVED>
Organization: M=E9t=E9o-France
Reply-To: E-MAIL-REMOVED, E-MAIL-REMOVED
Date: Wed, 13 Jun 2001 14:09:06 +0200
To: Daryle Walker <E-MAIL-REMOVED>
Subject: Re: Congruency (MORE)
Somewhere in the E.U., le 13/06/2001
Hi
After firing up my first reply to your E-mail, I thought some
more :-)
.
Daryle Walker wrote:
>=20
> on 6/11/01 4:40 AM, Hubert HOLIN at E-MAIL-REMOVED wrote:
>=20
> > Somewhere in the E.U., le 11/06/2001
> >
> > Daryle Walker wrote:
> >>
> >> on 6/9/01 6:27 PM, Hubert HOLIN at E-MAIL-REMOVED wrote:
[SNIP]
> > What I meant is that (from experience) some users that we want to
> > target will want to work with numbers which behave like integers but
> > which will not fit into any built-in (perhaps even including extensio=
ns
> > such as "long long"). These users will be using a class for that (mos=
t
> > likely a template based upon some built-in such as "long"). They will
> > also want to instanciate the congruency class (because they need it)
> > using that class. That's why we need a two-template arguments form su=
ch
> > as "template <typename T, T endpoint> class congruency {...}".
>=20
> But your "T" cannot be just any type! Section 14.1 of the standard lis=
ts
> what types a value-based template parameter can or cannot be. The
> system-laid-out types I mentioned are just about all you could use for =
your
> "T." Class types are specifically forbidden. Unless you expect users =
to
> define modular ranges with enumerated types, the built-in integer types=
are
> your only option for "T," so you might as well stick with the largest
> available type, "unsigned long." A workaround would be to use a pointe=
r or
> reference to a class object (make "endpoint" a "T*" or "T&"), but then =
your
> class object would have to be a global to have enough external linkage =
as a
> template parameter.
[BIG SNIP]
I believe we are, in fact, both correct.
Given my definition of "congruency" as above, the following code
should be illegal, for the reasons you state:
conguency<double, 5.0> y;
but the following one must be correct:
congruency< pair<long>, 5> z;
(assuming "pair" only introduces entities of the same category than that
of its parameter, or pointers, references and arrays thereof).
The reason is that C++ is not allowed to use as template
parameters
floating entities whose coding is essentially platform-dependant (as per
the rules you cite), but is allowed to use integer entities whose
meaning should be (good luck if you come from a platform where "char"
happens to bit 16 bits long and you use a value which does not fit into
8 bits...).
For what we intend to do I believe we are safe, even with the
two-parameters version.
It may be worthwile to move this discution to comp.std.c++ as
there
may be cause for a couple of DR. Would you do it?
--=20
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT 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: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 18 Jun 2001 13:32:23 GMT Raw View
[MOD: please ignore my previous reply to this message - it has no new
content]
"Daryle Walker" <dwalker07@snet.net.invalid> wrote in message
news:1euxx2t.1cc8oj9e05hyN%dwalker07@snet.net.invalid...
I was having an e-mail conversation with someone else about a plan for a
class template. We disagreed on what types are allowed to be used in
value-based (a.k.a. non-type, non-template) template parameters. The
other guy noted that the standard supports both our views, and so the
standard guys need to fix it. Here's a copy of our last correspondence.
[SNIP]
> > > What I meant is that (from experience) some users that we want to
> > > target will want to work with numbers which behave like integers but
> > > which will not fit into any built-in (perhaps even including
extensions
> > > such as "long long"). These users will be using a class for that (most
> > > likely a template based upon some built-in such as "long"). They will
> > > also want to instanciate the congruency class (because they need it)
> > > using that class. That's why we need a two-template arguments form
such
> > > as "template <typename T, T endpoint> class congruency {...}".
> >
> > But your "T" cannot be just any type! Section 14.1 of the standard
lists
> > what types a value-based template parameter can or cannot be. The
> > system-laid-out types I mentioned are just about all you could use for
your
> > "T." Class types are specifically forbidden. Unless you expect users
to
> > define modular ranges with enumerated types, the built-in integer types
are
> > your only option for "T," so you might as well stick with the largest
> > available type, "unsigned long." A workaround would be to use a pointer
or
> > reference to a class object (make "endpoint" a "T*" or "T&"), but then
your
> > class object would have to be a global to have enough external linkage
as a
> > template parameter.
>
> [BIG SNIP]
>
> I believe we are, in fact, both correct.
>
> Given my definition of "congruency" as above, the following code
> should be illegal, for the reasons you state:
>
> conguency<double, 5.0> y;
Correct, this is illegal, as floating point values are not permitted
> but the following one must be correct:
>
> congruency< pair<long>, 5> z;
Given the above definition, this line is also illegal. Firstly, "5" is not a
value of type "pair<long>". Secondly, values of type "pair<long>" are not
permitted as template parameters, so this particular template specialization
can never be instantiated.
> (assuming "pair" only introduces entities of the same category than that
> of its parameter, or pointers, references and arrays thereof).
>
> The reason is that C++ is not allowed to use as template
> parameters
> floating entities whose coding is essentially platform-dependant (as per
> the rules you cite), but is allowed to use integer entities whose
> meaning should be (good luck if you come from a platform where "char"
> happens to bit 16 bits long and you use a value which does not fit into
> 8 bits...).
>
> For what we intend to do I believe we are safe, even with the
> two-parameters version.
>
> It may be worthwile to move this discution to comp.std.c++ as
> there
> may be cause for a couple of DR. Would you do it?
DR - no. Feature request - yes.
A while back, I posted a message about a very similar thing - I was trying
to write a range<typename T,T min,T max> template which would allow T to be
a class type (e.g. a range<> with a larger span, to allow subranges.)
However, the result was that there is no simple way to do it. The best was
range<typename T,const T& min,const T&max>, which permitted user-supplied
values. However, these have to have external linkage, and there is no way of
restricting the actual objects to be const - the user could pass a non-const
object, which would then compile, but the value could be changed later. You
could keep a copy, but this seems overkill - you need to have distinct
external-linkage values for different ranges, to make them different types,
so storing a copy of these distinct values is wasteful. This approach also
means that you have to supply external-linkage values for simple types like
"int" as well, which seems silly.
The problem with permitting floating point and class types is how to name
them so that the same template instantiation is used from different
translation units. For obvious reasons, non-type template parameters have to
be compile-time constants. However, the construction of floating-point and
class objects can be a run-time process. How then do we associate
std::string("hello") from one unit with std::string("hello") from another,
or 1.0 vs 5.0/5.0?
I suppose the compiler could keep track of which constructors were called
with which values, but then take the std::string example - the compiler
would have to know that it was the value of the literal that was important,
not the (const char*) address. Basically, I don't think this is possible.
A feature which could be used for similar things is some way to guarantee
that a const reference is bound to a const object, but I can't think how
this could be expressed syntactically ("T really const& ref" => ref is a
reference to a T object that is itself const ;)
Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer
---
[ comp.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 ]