Topic: Template instantiation & conditional operator


Author: Matt Austern <austern@apple.com>
Date: Tue, 16 Apr 2002 17:46:31 GMT
Raw View
In article <fl1ydz2vc1.fsf@jambon.cmla.ens-cachan.fr>,
 Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr> wrote:

> "James Kuyper Jr." <kuyper@wizard.net> writes:
>
> [...]
>
> | The standard recommends
> | that an implementation support at least 17 levels of template recursion.
>
> Exact.  I'm, however, wondering about that number.  What is so magic
> about 17?

Nothing.  It was deliberately chosen to be a senseless looking number.
It was supposed to be obvious that the number '17' was chosen
arbitrarily, and that there was no technical discussion that led to that
choice.  The idea was that if anyone ever did have a good technical
argument for some number, then it could be changed to something sensible.

Note also that Annex B, where this number appears, is not normative.

---
[ comp.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: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Tue, 16 Apr 2002 19:00:18 GMT
Raw View
Matt Austern <austern@apple.com> writes:

| In article <fl1ydz2vc1.fsf@jambon.cmla.ens-cachan.fr>,
|  Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr> wrote:
|
| > "James Kuyper Jr." <kuyper@wizard.net> writes:
| >
| > [...]
| >
| > | The standard recommends
| > | that an implementation support at least 17 levels of template recursion.
| >
| > Exact.  I'm, however, wondering about that number.  What is so magic
| > about 17?
|
| Nothing.  It was deliberately chosen to be a senseless looking number.

Ah, that at least makes sense :-)  A friend asked the rationale
behind that number, I was unable to give any answer (other than saying
it is prime ;-).  Here, I took the opportunity to sharpen my knowledge
about that finally not-so-magic
number.

| It was supposed to be obvious that the number '17' was chosen
| arbitrarily, and that there was no technical discussion that led to that
| choice.  The idea was that if anyone ever did have a good technical
| argument for some number, then it could be changed to something sensible.

Therefore, I conclude that the "existing pratice" isn't an argument.
Now about "it is a prime, twin with 19"?

--
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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Tue, 9 Apr 2002 00:16:51 GMT
Raw View
"James Kuyper Jr." <kuyper@wizard.net> writes:

| Gabriel Dos Reis wrote:
| >
| > "James Kuyper Jr." <kuyper@wizard.net> writes:
| >
| > [...]
| >
| > | The standard recommends
| > | that an implementation support at least 17 levels of template recursion.
| >
| > Exact.  I'm, however, wondering about that number.  What is so magic
| > about 17?  That is, why 17 and not 15, nor 16, nor any other power of 2
| > minus one?
|
| I'd guess that this number was chosen by the committee based upon
| existing practice.

I can understand that magic number was inpired by an existing
pratice.  Then, my question would be why the hypothetical existing
pratice had that number.

--
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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Sun, 7 Apr 2002 06:01:50 GMT
Raw View
[To the moderator: I posted this on 3 April, but it seems that it got
lost. Thanks :)]


On Mon,  1 Apr 2002 21:59:41 CST, "James Kuyper Jr."
<kuyper@wizard.net> wrote:

[...]
>I don't think your code should be made legal. Using ?: makes it
>nominally a run-time operation, which it can't be. Allowing your code
>would require that all C++ compilers recognise that a given branch in
>the code won't be taken, and to avoid generating the code that would
>have been executed if it had been.

This is not to defend my code (which isn't worth ;) ), but there's
nothing concerning run-time and branches of execution here; the
inizializer of value is an integral constant expression, just like in:

int const which_one = 1;
int array [which_one? 3 : 0];


Genny.

---
[ comp.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: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Mon, 1 Apr 2002 02:49:38 CST
Raw View
Hi everybody,
consider the following trivial code to compute the rank of an array:

template<typename T>
struct rank; // not defined

template <typename T, std::size_t N>
struct rank<T[N]> {
 static std::size_t const value = 1 + is_array<T>::value?
(rank<T>::value) : 0;
};

What does the standard say about the rank<T>::value operand? Must the
compiler try to specialize on the type T anyway or skip the whole
expression and evaluate the 0 only?

Note that this determine whether the code is valid or it causes always
an error (use of undefined type).


Genny.

---
[ comp.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: Mon, 1 Apr 2002 16:26:51 GMT
Raw View
Gennaro Prota wrote:
>
> Hi everybody,
> consider the following trivial code to compute the rank of an array:
>
> template<typename T>
> struct rank; // not defined
>
> template <typename T, std::size_t N>
> struct rank<T[N]> {
>  static std::size_t const value = 1 + is_array<T>::value?
> (rank<T>::value) : 0;
> };
>
> What does the standard say about the rank<T>::value operand? Must the
> compiler try to specialize on the type T anyway or skip the whole
> expression and evaluate the 0 only?
>
> Note that this determine whether the code is valid or it causes always
> an error (use of undefined type).

Yes, it must be able to instantiate rank<T>. Therefore, is_array<T>
(whatever that is) won't achieve the desired affect. You've defined a
recursive family of template instantiations. The standard recommends
that an implementation support at least 17 levels of template recursion.
However, like most such numerical limits, it doesn't require that an
implementation even support 1 level of recursion. However, I prefer to
pretend that this feature of the standard has been fixed, and that the
recommended minimum limits in Annex B are actually required; otherwise
C++ would be almost useless.

The solution to this problem is to terminate the recursion. Provide a
default definition that unconditionally sets the rank to 0. That
definition will be used for all non-arrays. The specialization for
arrays will always be preferred over the unspecialized version, for any
type which is an array.

---
[ comp.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: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Mon, 1 Apr 2002 21:39:29 GMT
Raw View
On Mon,  1 Apr 2002 16:26:51 GMT, "James Kuyper Jr."
<kuyper@wizard.net> wrote:

[...]
>Yes, it must be able to instantiate rank<T>. Therefore, is_array<T>
>(whatever that is) won't achieve the desired affect.

Thanks a lot James :) But, could there actually be any problems in not
requiring instantiation?

> You've defined a
>recursive family of template instantiations. The standard recommends
>that an implementation support at least 17 levels of template recursion.
>However, like most such numerical limits, it doesn't require that an
>implementation even support 1 level of recursion. However, I prefer to
>pretend that this feature of the standard has been fixed, and that the
>recommended minimum limits in Annex B are actually required; otherwise
>C++ would be almost useless.

I'd rather say that Annex B would is almost useless ;) (joking...)
I think this is the old problem of "let us support all the platforms
of the universe" that often afflicts standard requirements. (Since,
AFAIK, the reason why limits in Annex B are only recommended is that
it was impossible to fix values acceptable for all possible C++
targets). But it seems to me that the trend is to adopt a different
view on this kind of situations; for instance threads will be very
probably standardized, even though they can't be implemented on some
platforms. Am I right about this being the current "feeling" in the
committee?

>
>The solution to this problem is to terminate the recursion. Provide a
>default definition that unconditionally sets the rank to 0. That
>definition will be used for all non-arrays. The specialization for
>arrays will always be preferred over the unspecialized version, for any
>type which is an array.

Yes, obviously the reason why I didn't write

template<typename T>
struct rank {
   static std::size_t const value = 0;
};

is that I didn't want client code to take the rank of a non-array
type.

Of course there are still many ways to get this effect, but I'd have
liked this to be legal, since it looks quite elegant to me.

If it was possible to declare partial specializations as friend,
another solution could have been BTW to declare value as a private in
the primary template, and then rank<T[N]> as a friend of rank.


Thanks again for your clear reply :)
Genny.

---
[ comp.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: Mon, 1 Apr 2002 22:12:11 GMT
Raw View
"James Kuyper Jr." <kuyper@wizard.net> writes:

[...]

| The standard recommends
| that an implementation support at least 17 levels of template recursion.

Exact.  I'm, however, wondering about that number.  What is so magic
about 17?  That is, why 17 and not 15, nor 16, nor any other power of 2
minus one?

| However, like most such numerical limits, it doesn't require that an
| implementation even support 1 level of recursion.

So what about std::vector<> in a hosted implementation?

--
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: "James Kuyper Jr." <kuyper@wizard.net>
Date: Tue, 2 Apr 2002 00:42:37 GMT
Raw View
Gennaro Prota wrote:
>
> On Mon,  1 Apr 2002 16:26:51 GMT, "James Kuyper Jr."
> <kuyper@wizard.net> wrote:
....
> Yes, obviously the reason why I didn't write
>
> template<typename T>
> struct rank {
>    static std::size_t const value = 0;
> };
>
> is that I didn't want client code to take the rank of a non-array
> type.

That's not obvious to me. A rank of 0 would be the correct rank for a
non-array type, as far as I can see.

---
[ comp.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: Tue, 2 Apr 2002 03:59:00 GMT
Raw View
Gabriel Dos Reis wrote:
>
> "James Kuyper Jr." <kuyper@wizard.net> writes:
>
> [...]
>
> | The standard recommends
> | that an implementation support at least 17 levels of template recursion.
>
> Exact.  I'm, however, wondering about that number.  What is so magic
> about 17?  That is, why 17 and not 15, nor 16, nor any other power of 2
> minus one?

I'd guess that this number was chosen by the committee based upon
existing practice. The existing practice was probably based upon space
limitations in a particular environment. But that's just guesswork on my
part.

> | However, like most such numerical limits, it doesn't require that an
> | implementation even support 1 level of recursion.
>
> So what about std::vector<> in a hosted implementation?

You'll have to clarify your point; I don't see it offhand. It's not
obvious to me that template recursion is required to implement
std::vector<>. However, even if it is, that would simply mean that
std::vector<> must work, despite using that feature. It doesn't mean
that if you took the source code for std::vector<>, and re-wrote it to
avoid using names reserved to the implementation, that it would work
just like std::vector<>. An implementation is free to allow more levels
of recursion for it's own code, than for user code.

---
[ comp.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: Mon, 1 Apr 2002 21:59:41 CST
Raw View
(I should have included this in my previous reply, but I didn't think of
it at the time)

Gennaro Prota wrote:
....
> Of course there are still many ways to get this effect, but I'd have
> liked this to be legal, since it looks quite elegant to me.

I don't think your code should be made legal. Using ?: makes it
nominally a run-time operation, which it can't be. Allowing your code
would require that all C++ compilers recognise that a given branch in
the code won't be taken, and to avoid generating the code that would
have been executed if it had been. I think that's a reasonable
optimization to hope for, but not something the standard should mandate.

Makeing sure that rank=0 involves a different definition than higher
ranks strikes me as exactly the right way to terminate this kind of
recursion.

---
[ comp.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                ]