Discussion:
[std-discussion] non-constant constant-expressions, is it really possible?
Filip Roséen
2015-04-26 17:37:00 UTC
Permalink
Good evening [std-discussion],

I just finished an article/blog post that in detail explains a technique
that adds "state" to *constant-expressions*;

- http://b.atch.se/posts/non-constant-constant-expressions/

Though, the question is whether there is any part of the standard (C++11)
that renders the technique explained *ill-formed*, or to suffer from
*undefined-behavior*?
Best Regards,

Filip Roséen
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Chris Hallock
2015-04-26 23:09:38 UTC
Permalink
Does the last restriction in 14.6/8 put a stick through the spokes?

[...] If a hypothetical instantiation of a template immediately following
its definition would be ill-formed due to a construct that does not depend
on a template parameter, the program is ill-formed; no diagnostic is
required. *If the interpretation of such a construct in the hypothetical
instantiation is different from the interpretation of the corresponding
construct in any actual instantiation of the template, the program is
ill-formed; no diagnostic is required.* [...]

(This wording is not in C++14 but was added to the working draft by DR#1850
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1850>.)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-26 23:40:18 UTC
Permalink
<html><head></head><body style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">Hmm, I don't think it applies - an instantiation of the template would never be ill-formed.<span style="font-family: Calibri, 'Slate Pro', sans-serif; font-size: initial; text-align: initial; line-height: initial;">&nbsp;</span><br><br>As from the defect report; "<span style="color: rgb(0, 0, 0); font-family: sans-serif;"></span><span style="font-family: sans-serif; line-height: initial;">Presumably a rule is needed to make it ill-formed, no diagnostic required, if the validity of such a reference changes between the two contexts.‎"</span><span style="font-family: sans-serif; font-size: initial; text-align: initial; line-height: initial;"></span></div><div style="width: 100%; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"><font color="#1f497d" face="Calibri, Slate Pro, sans-serif"><br></font></div><div style="width: 100%; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"><font color="#1f497d" face="Calibri, Slate Pro, sans-serif">The template is valid no matter where it is instantiated, however.. it wouldn't be if we were to actually try and evaluate the constexpr function call `flag(0)` in the post (but that doesn't happen).<br><br>The section that follows your quote deals with evaluation of constant-expressions (among other things), and says that an evaluation of an undefined constant-expression would render the template ill-formed; the "problem" is that we never evaluate the function call (since it is an unevaluated operand to `noexcept`).</font></div> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br style="display:initial"></div> <div style="font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">::&nbsp;Filip&nbsp;Roséen&nbsp;(via&nbsp;BlackBerry)<br>::&nbsp;+46701448424&nbsp;<br>::&nbsp;***@gmail.com<br><br></div> <table width="100%" style="background-color:white;border-spacing:0px;"> <tbody><tr><td colspan="2" style="font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"> <div style="border-style: solid none none; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in 0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> <div><b>From: </b>Chris Hallock</div><div><b>Sent: </b>Monday, April 27, 2015 1:09 AM</div><div><b>To: </b>std-***@isocpp.org</div><div><b>Reply To: </b>std-***@isocpp.org</div><div><b>Subject: </b>[std-discussion] Re: non-constant constant-expressions, is it really possible?</div></div></td></tr></tbody></table><div style="border-style: solid none none; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"></div><br><div id="_originalContent" style=""><div dir="ltr">Does the last restriction in 14.6/8 put a stick through the spokes?<br><br><div style="margin-left: 40px;"><span style="color: rgb(56, 118, 29);">[...] If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required. <b>If the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template, the program is ill-formed; no diagnostic is required.</b> [...]</span><br></div><br>(This wording is not in C++14 but was added to the working draft by <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1850">DR#1850</a>.)<br></div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br>
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br>
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br>
<br><!--end of _originalContent --></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Discussion&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br />
Columbo
2015-04-27 00:13:27 UTC
Permalink
Post by Filip Roséen
an instantiation of the template would never be ill-formed.
IMO, the second sentence is actually independent from whether the first one
applies (regarding the legality). It should be equivalent to

If the interpretation of a construct that does not depend on a template
Post by Filip Roséen
parameter in a hypothetical instantiation immediately following the
template is different from the interpretation of the corresponding
construct in any actual instantiation of the template, the program is
ill-formed; no diagnostic is required.
Now consider that your template includes the non-dependent construct noexcept
(flag (0)), the 'interpretation' of which is indeed different between the
instantiation of f<> right after the template,and the instantiation of f<> at
the second point. So if my reading is correct, your program is ill-formed
NDR, well, at least according to the latest draft.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-04-26 23:37:47 UTC
Permalink
Post by Filip Roséen
Good evening [std-discussion],
I just finished an article/blog post that in detail explains a technique that adds "state" to constant-expressions;
http://b.atch.se/posts/non-constant-constant-expressions/
Though, the question is whether there is any part of the standard (C++11) that renders the technique explained ill-formed, or to suffer from undefined-behavior?
A friend function defined in a class template is treated as if it were defined at the point of instantiation of the specialization ([temp.inject] §14.6.5). The point of instantiation is retroactively before any non-template function declaration or definition which incurred the chain of instantiations leading to the friend, if the outermost instantiation was a function ([temp.point] 14.6.4.1; this distinction is arbitrary but significant in this context).
The existence of such a friend may be observed after the point of instantiation, but before the specialization has been mentioned within the function. This does not violate [temp.dep.candidate] 14.6.4.2 because there are not two valid specializations in two instantiation contexts, but only one correct interpretation which is impossible because the initial instantiation context depends on things at the point of instantiation which do not yet exist.
constexpr int get();
template< int value >
class set { // Instantiate this exactly once.
friend constexpr int get() { return value; }
};
// Point of instantiation is here.
int main() {
char a[ get() ]; // OK but impossible: get() was already defined at the POI.
set< 5 > b;
char c[ get() ]; // This is also well-defined, and it actually works.
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-04-27 01:28:21 UTC
Permalink
Post by Filip Roséen
Good evening [std-discussion],
I just finished an article/blog post that in detail explains a technique
that adds "state" to *constant-expressions*;
- http://b.atch.se/posts/non-constant-constant-expressions/
Though, the question is whether there is any part of the standard (C++11)
that renders the technique explained *ill-formed*, or to suffer from
*undefined-behavior*?
I know of no language rule that this technique violates, but it does slip
past one rule on a technicality (that a template specialization that has
multiple points of instantiation behaves the same at all of them) --
because the default template arguments aren't part of the instantiated
specialization itself.

If we wanted for this to not be OK, I think one natural way to get that
effect would be to say that you can only use information from a friend
defined inline in a class if that class was an associated class of the name
lookup that found the friend -- that friends defined inline are "ADL-only"
-- but that might break a lot of reasonable code.

Another natural way might be to say that *any* substitution (including
template parameters, default arguments, etc) must give the same results at
all points of substitution, not just template instantiations.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-04-27 01:44:34 UTC
Permalink
Another natural way might be to say that *any* substitution (including template parameters, default arguments, etc) must give the same results at all points of substitution, not just template instantiations.
I occasionally use default arguments to get different meanings from one template-id. It’s the only way to define the trait is_incomplete. (However, that’s a somewhat dangerous trait, and I don’t recall another use offhand, aside from working around some compiler bugs.)

Otherwise, the technique looks similar to the one I described, and it has the same point-of-instantiation weakness. This should be described in the article. Currently the point-of-instantiation rules are merely referenced, but there’s no discussion of what it means for usage of the library.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 04:28:42 UTC
Permalink
<html><head></head><body class="" style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">Hmm, I am not sure I agree with your wording related to the point of instantiation, because the explicit specialization is not there until we have actually seen the (implicit) instantiation happen; that's my take on the relevant sections of the Standard.<br><br>14.6.5p1 (n3337) says "when a template is instantiated", in my book this (and other sections) means that such state cannot leak out prior to the instantiation.</div><div style="width: 100%; font-size: initial; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: Calibri, 'Slate Pro', sans-serif; font-size: initial; text-align: initial; line-height: initial;"><br>You can always point (with your finger) at an instantiations "point of instantiation", but the effects of such instantiation are not present until we have actually instantiated it.</span></div><div style="width: 100%; font-size: initial; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br><font face="Calibri, Slate Pro, sans-serif">This is addressed in the blog post as; "</font><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">It is important to note that a&nbsp;</span><em style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">point of instantation</em><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">&nbsp;</span><code style="font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(153, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">(1)</code><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">&nbsp;denotes in what&nbsp;</span><em style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">context</em><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">&nbsp;the compiler may generate the relevant code. What triggers</span><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">&nbsp;the instantiation is where the change actually takes effect (</span><code style="font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(153, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">(2)</code><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">&nbsp;and&nbsp;</span><code style="font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(153, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">(3)</code><span style="font-family: sans-serif; color: rgb(0, 0, 0); text-align: justify; background-color: rgb(255, 249, 227);">)."<span style="font-size: initial; line-height: initial;"></span><br></span><font face="Calibri, Slate Pro, sans-serif"><br></font></div><div style="width: 100%; font-size: initial; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><font face="Calibri, Slate Pro, sans-serif">Sorry for the potentially weird formatting; I'm currently on my phone!</font></div> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br style="display:initial"></div> <div style="font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">::&nbsp;Filip&nbsp;Roséen&nbsp;(via&nbsp;BlackBerry)<br>::&nbsp;+46701448424&nbsp;<br>::&nbsp;***@gmail.com<br><br></div> <table width="100%" style="background-color:white;border-spacing:0px;"> <tbody><tr><td colspan="2" style="font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"> <div style="border-style: solid none none; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in 0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> <div><b>From: </b>David Krauss</div><div><b>Sent: </b>Monday, April 27, 2015 3:44 AM</div><div><b>To: </b>std-***@isocpp.org</div><div><b>Reply To: </b>std-***@isocpp.org</div><div><b>Subject: </b>Re: [std-discussion] non-constant constant-expressions, is it really possible?</div></div></td></tr></tbody></table><div style="border-style: solid none none; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"></div><br><div id="_originalContent" style=""><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On 2015–04–27, at 9:28 AM, Richard Smith &lt;<a href="mailto:***@metafoo.co.uk" class="">***@metafoo.co.uk</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Another natural way might be to say that *any* substitution (including template parameters, default arguments, etc) must give the same results at all points of substitution, not just template instantiations.</span></div></blockquote></div><br class=""><div class="">I occasionally use default arguments to get different meanings from one template-id. It’s the only way to define the trait <font face="Courier" class="">is_incomplete</font>. (However, that’s a somewhat dangerous trait, and I don’t recall another use offhand, aside from working around some compiler bugs.)</div><div class=""><br class=""></div><div class="">Otherwise, the technique looks similar to the one I described, and it has the same point-of-instantiation weakness. This should be described in the article. Currently the point-of-instantiation rules are merely referenced, but there’s no discussion of what it means for usage of the library.</div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br>
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br>
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br>
<br><!--end of _originalContent --></div><br></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Discussion&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br />
David Krauss
2015-04-27 05:31:59 UTC
Permalink
Post by Filip Roséen
Hmm, I am not sure I agree with your wording related to the point of instantiation,
What wording? Please quote.
Post by Filip Roséen
because the explicit specialization is not there until we have actually seen the (implicit) instantiation happen; that's my take on the relevant sections of the Standard.
The problem is that the standard doesn’t describe an order for the instantiations to happen. Our examples rely on the idea that specializations used in prior statements will be instantiated before (or in an enclosing declarative scope to) ones in subsequent statements. But it would be just as conforming to process the function from the end to the beginning, or randomly.
Post by Filip Roséen
14.6.5p1 (n3337) says "when a template is instantiated", in my book this (and other sections) means that such state cannot leak out prior to the instantiation.
I disagree. Besides instantiations not having a well-defined order, there’s no sense temporality at all. The intent is that templates are mathematically pure and you can’t observe whether a template has yet been instantiated or not. Name lookup happens from a place or context in the program text, not a point in time, because there is no such thing as time.
Post by Filip Roséen
The intent is that it is a permissible implementation technique to do template instantiation at the end of a translation unit rather than at an actual point of instantiation. This idea is not reflected in the current rules, however.
(Note, this defect was accepted and resolved for C++11. The solution was to add additional points of instantiation, which I mention below.)

In other words, the intent of the committee thus far is that the compiler can plow through your entire function definition, and up to the end of the TU, without ever instantiating a friend.
Post by Filip Roséen
This is addressed in the blog post as; "It is important to note that a point of instantation (1) denotes in what context the compiler may generate the relevant code. What triggers the instantiation is where the change actually takes effect ((2) and (3)).”
Yes, but you’re skipping some major issues.

1. Your utility won’t work from inside a template. It must always be used from a non-template context, because a second instantiation of the same template would see the friends generated by the first instantiation. Every specialization that is used at all has at least two points of instantiation, including one at the end of the TU. (In practice, though, you will probably get consistent behavior for templates with only exactly two PoI’s.)

My utility specifically avoids this, by the way, because it only implements a map, and you’re not allowed to observe the absence of an entry in the map. Functions can progressively generate compile-time state, but not change it, and a query for non-existent state produces a failure.

2. Points of instantiation are defined for each specific kind of entity: after the enclosing namespace-scope declaration for “a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template” and before for “a class template specialization, a class member template specialization, or a specialization for a class member of a class template.”

Your utility requires the point instantiation of the friend function to be before the point of use. Otherwise, it wouldn’t be in scope. However, there is no point of instantiation defined for friends at all. You’re relying on friends being treated like classes, not like other functions, which seems especially brittle.

My utility avoids this by only relying on the declaration of the friend function: it’s never defined (instantiated) at all. The friend declaration, sans body, can more reasonably be regarded as part of the class.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 05:53:01 UTC
Permalink
Post by David Krauss
1. Your utility won’t work from inside a template. It must always be used
from a non-template context, because a second instantiation of the same
template would see the friends generated by the first instantiation. Every
specialization that is used at all has at least two points of
instantiation, including one at the end of the TU. (In practice, though,
you will probably get consistent behavior for templates with only exactly
two PoI’s.)

Unless they rely on different friends, so the above is not really an issue,
also; class template specializations has at most one point of instantiation
- not two, that only applies to function templates.
Post by David Krauss
The problem is that the standard doesn’t describe an order for the
instantiations to happen.

Unless we are talking dependency, where it must happen in some order - this
does not only include literally dependent types. The example in the current
post is not sufficient enough to explain this in detail, but an explanation
will be included in upcoming posts (there are more neat little tricks to be
published).
Post by David Krauss
Your utility requires the point instantiation of the friend function to
be before the point of use. Otherwise, it wouldn’t be in scope. However,
there is no point of instantiation defined for friends at all. You’re
relying on friends being treated like classes, not like other functions,
which seems especially brittle.

This is not entirely true, it requires the point of instantiation of the
class-template specialization to be where it needs to be; please note that
default template-arguments are *not* part of the specialization itself,
that means that `sizeof(...)` used as a default-argument to the template
function effectively puts the instantiation of the relevant class prior to
`main` (not prior to the instantiation of the function template
specialization). The post "abuses" the instantiation of class template
specializations, not function template specializations.


By the way, a variation of your method is what makes some other stuff
possible to implement - it is not directly equivalent, but it is somewhat
similar. I will however explain this in detail in upcoming posts.
Post by David Krauss
Hmm, I am not sure I agree with your wording related to the point of instantiation,
What wording? Please quote.
because the explicit specialization is not there until we have actually
seen the (implicit) instantiation happen; that's my take on the relevant
sections of the Standard.
The problem is that the standard doesn’t describe an order for the
instantiations to happen. Our examples rely on the idea that
specializations used in prior statements will be instantiated before (or in
an enclosing declarative scope to) ones in subsequent statements. But it
would be just as conforming to process the function from the end to the
beginning, or randomly.
14.6.5p1 (n3337) says "when a template is instantiated", in my book this
(and other sections) means that such state cannot leak out prior to the
instantiation.
I disagree. Besides instantiations not having a well-defined order,
there’s no sense temporality at all. The intent is that templates are
mathematically pure and you can’t observe whether a template has yet been
instantiated or not. Name lookup happens from a place or context in the
program text, not a point in time, because there is no such thing as time.
I would like to propose a guaranteed beginning-to-end order of statements
and to introduce finer scoping so that our tricks will work. But it’s a
The intent is that it is a permissible implementation technique to do
template instantiation at the end of a translation unit rather than at an
actual point of instantiation. This idea is not reflected in the current
rules, however.
(Note, this defect was accepted and resolved for C++11. The solution was
to add additional points of instantiation, which I mention below.)
In other words, the intent of the committee thus far is that the compiler
can plow through your entire function definition, and up to the end of the
TU, without ever instantiating a friend.
This is addressed in the blog post as; "It is important to note that a *point
of instantation* (1) denotes in what *context* the compiler may generate
the relevant code. What triggers the instantiation is where the change
actually takes effect ((2) and (3)).”
Yes, but you’re skipping some major issues.
1. Your utility won’t work from inside a template. It must always be used
from a non-template context, because a second instantiation of the same
template would see the friends generated by the first instantiation. Every
specialization that is used at all has at least two points of
instantiation, including one at the end of the TU. (In practice, though,
you will probably get consistent behavior for templates with only exactly
two PoI’s.)
My utility specifically avoids this, by the way, because it only
implements a map, and you’re not allowed to observe the absence of an entry
in the map. Functions can progressively generate compile-time state, but
not change it, and a query for non-existent state produces a failure.
after the enclosing namespace-scope declaration for “a function template
specialization, a member function template specialization, or a
specialization for a member function or static data member of a
class template” and before for “a class template specialization, a class
member template specialization, or a specialization for a class member of a
class template.”
Your utility requires the point instantiation of the friend function to be
before the point of use. Otherwise, it wouldn’t be in scope. However, there
is no point of instantiation defined for friends at all. You’re relying on
friends being treated like classes, not like other functions, which seems
especially brittle.
My utility avoids this by only relying on the declaration of the friend
function: it’s never defined (instantiated) at all. The friend declaration,
sans body, can more reasonably be regarded as part of the class.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-04-27 06:35:04 UTC
Permalink
Post by Filip Roséen
Post by David Krauss
1. Your utility won’t work from inside a template. It must always be used from a non-template context, because a second instantiation of the same template would see the friends generated by the first instantiation. Every specialization that is used at all has at least two points of instantiation, including one at the end of the TU. (In practice, though, you will probably get consistent behavior for templates with only exactly two PoI’s.)
Unless they rely on different friends, so the above is not really an issue,
You mean the two instantiations of the same specialization would access different friends? That’s ill-formed, NDR.
Post by Filip Roséen
also; class template specializations has at most one point of instantiation - not two, that only applies to function templates.
Your utility is only intended for use within functions, so those are what’s relevant.
Post by Filip Roséen
Post by David Krauss
The problem is that the standard doesn’t describe an order for the instantiations to happen.
Unless we are talking dependency, where it must happen in some order - this does not only include literally dependent types. The example in the current post is not sufficient enough to explain this in detail, but an explanation will be included in upcoming posts (there are more neat little tricks to be published).
There is no dependency between the statements in your post, and that seems to be the whole purpose: to let compile-time information flow from one statement to the next without using the type system.

It would be more responsible to provide a disclaimer in your article if you believe its examples to be nonconforming, especially if an edit is in the works.
Post by Filip Roséen
Post by David Krauss
Your utility requires the point instantiation of the friend function to be before the point of use. Otherwise, it wouldn’t be in scope. However, there is no point of instantiation defined for friends at all. You’re relying on friends being treated like classes, not like other functions, which seems especially brittle.
This is not entirely true, it requires the point of instantiation of the class-template specialization to be where it needs to be;
Calling the constexpr function requires its definition to precede the use. You’re assuming that the functions are defined by the class template instantiation: “Please note that the functions func (short) and func (float) are undefined until A<short> and A<float> have been instantiated, respectively.” This is not a safe assumption, because the point of instantiation may render the definition invisible to the current function.
Post by Filip Roséen
please note that default template-arguments are not part of the specialization itself, that means that `sizeof(...)` used as a default-argument to the template function effectively puts the instantiation of the relevant class prior to `main` (not prior to the instantiation of the function template specialization). The post "abuses" the instantiation of class template specializations, not function template specializations.
I’m not sure what you mean by “prior to the instantiation of the function template specialization.” Points of instantiation are before or after non-template declarations at namespace scope. Classes come before, functions come after. Friends are unspecified, but they are functions, so we can extrapolate.

Actually, constexpr function templates can’t usually form constant expressions at all according to the current rules. This needs a DR.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-04-27 06:41:13 UTC
Permalink
Post by David Krauss
Post by David Krauss
1. Your utility won’t work from inside a template. It must always be
used from a non-template context, because a second instantiation of the
same template would see the friends generated by the first instantiation.
Every specialization that is used at all has at least two points of
instantiation, including one at the end of the TU. (In practice, though,
you will probably get consistent behavior for templates with only exactly
two PoI’s.)
Unless they rely on different friends, so the above is not really an issue,
You mean the two instantiations of the same specialization would access
different friends? That’s ill-formed, NDR.
also; class template specializations has at most one point of
instantiation - not two, that only applies to function templates.
Your utility is only intended for use within functions, so those are what’s relevant.
Post by David Krauss
The problem is that the standard doesn’t describe an order for the
instantiations to happen.
Unless we are talking dependency, where it must happen in some order -
this does not only include literally dependent types. The example in the
current post is not sufficient enough to explain this in detail, but an
explanation will be included in upcoming posts (there are more neat little
tricks to be published).
There is no dependency between the statements in your post, and that seems
to be the whole purpose: to let compile-time information flow from one
statement to the next without using the type system.
It would be more responsible to provide a disclaimer in your article if
you believe its examples to be nonconforming, especially if an edit is in
the works.
Post by David Krauss
Your utility requires the point instantiation of the friend function to
be before the point of use. Otherwise, it wouldn’t be in scope. However,
there is no point of instantiation defined for friends at all. You’re
relying on friends being treated like classes, not like other functions,
which seems especially brittle.
This is not entirely true, it requires the point of instantiation of the
class-template specialization to be where it needs to be;
Calling the constexpr function requires its definition to precede the use.
You’re assuming that the functions are defined by the class template
instantiation: “Please note that the functions func (short) and func
(float) are *undefined* until A<short> and A<float> have been
instantiated, respectively.” This is not a safe assumption, because the
point of instantiation may render the definition invisible to the current
function.
please note that default template-arguments are *not* part of the
specialization itself, that means that `sizeof(...)` used as a
default-argument to the template function effectively puts the
instantiation of the relevant class prior to `main` (not prior to the
instantiation of the function template specialization). The post "abuses"
the instantiation of class template specializations, not function template
specializations.
I’m not sure what you mean by “prior to the instantiation of the function
template specialization.” Points of instantiation are before or after
non-template declarations at namespace scope. Classes come before,
functions come after. Friends are unspecified, but they are functions, so
we can extrapolate.
Actually, constexpr function templates can’t usually form constant
expressions at all according to the current rules. This needs a DR.
FYI, this should be covered by core issue 1581 -- we're essentially
planning to require that constexpr function template specializations are
instantiated "at" the first point of reference (presumably with a single
PoI before the current declaration, like a class template specialization).
And likewise for function templates with a deduced return type.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 06:57:15 UTC
Permalink
<html><head></head><body class="" style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">‎&gt;&nbsp;<span style="font-family: Calibri, 'Slate Pro', sans-serif; line-height: initial;"></span><span style="font-family: sans-serif; line-height: initial;">You mean the two instantiations of the same specialization would access different friends? That’s ill-formed, NDR.</span></div> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">No, two different specializations of the same template (of course).</div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">&gt; <span style="font-family: sans-serif; line-height: initial;">Your utility is only intended for use within functions, so those are what’s relevant.</span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;"><br></span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;">I think you are focusing on the wrong part; the instantiation order of the functions has nothing to do with the template default-arguments (which effectively instantiates the class template).. the template default-arguments are what is important.</span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;"><br></span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;">In reply to the rest: the code is confirming, no edit is pending, there are cases where the order of function template instantiation matters - but the example provided is not one of them.<br><span style="line-height: initial; font-size: initial; text-align: initial;"><br></span></span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;"><span style="line-height: initial; font-size: initial; text-align: initial;">It is important to note that constexpr functions follow the same rules of normal functions, and just to make this even more clear one could also have expressed the method in the post by "abusing" default-arguments (non-template, regular arguments) since these expressions are said to be evaluated each time the function is invoked.<br><br>The use of a template instead of a non-template is simply because the upcoming examples will be working with a similar concept (since that is shorter, but regular function default-arguments can accomplish the same thing).</span></span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;"><br></span><span style="font-family: sans-serif; line-height: initial; font-size: initial; text-align: initial;"></span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-family: sans-serif; line-height: initial;"><br></span></div> <div style="font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">::&nbsp;Filip&nbsp;Roséen&nbsp;(via&nbsp;BlackBerry)<br>::&nbsp;+46701448424&nbsp;<br>::&nbsp;***@gmail.com<br><br></div> <table width="100%" style="background-color:white;border-spacing:0px;"> <tbody><tr><td colspan="2" style="font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"> <div style="border-style: solid none none; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in 0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> <div><b>From: </b>David Krauss</div><div><b>Sent: </b>Monday, April 27, 2015 8:35 AM</div><div><b>To: </b>std-***@isocpp.org</div><div><b>Reply To: </b>std-***@isocpp.org</div><div><b>Subject: </b>Re: [std-discussion] non-constant constant-expressions, is it really possible?</div></div></td></tr></tbody></table><div style="border-style: solid none none; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"></div><br><div id="_originalContent" style=""><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On 2015–04–27, at 1:53 PM, Filip Roséen &lt;<a href="mailto:***@gmail.com" class="">***@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class=""><div class="">&gt; 1. Your utility won’t work from inside a template. It must always be
used from a non-template context, because a second instantiation of the
same template would see the friends generated by the first
instantiation. Every specialization that is used at all has at least two
points of instantiation, including one at the end of the TU. (In
practice, though, you will probably get consistent behavior for
templates with only exactly two PoI’s.)<br class=""><br class=""></div>Unless they rely on different friends, so the above is not really an issue, </div></div></div></div></div></blockquote><div><br class=""></div><div>You mean the two instantiations of the same specialization would access different friends? That’s ill-formed, NDR.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class="">also; class template specializations has at most one point of instantiation - not two, that only applies to function templates.<br class=""></div></div></div></div></div></blockquote><div><br class=""></div><div>Your utility is only intended for use within functions, so those are what’s relevant.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class="">&gt; The problem is that the standard doesn’t describe an order for the instantiations to happen.<br class=""><br class=""></div>Unless we are talking dependency, where it must happen in some order - this does not only include literally dependent types. The example in the current post is not sufficient enough to explain this in detail, but an explanation will be included in upcoming posts (there are more neat little tricks to be published).<br class=""></div></div></div></div></blockquote><div><br class=""></div><div>There is no dependency between the statements in your post, and that seems to be the whole purpose: to let compile-time information flow from one statement to the next without using the type system.</div><div><br class=""></div><div>It would be more responsible to provide a disclaimer in your article if you believe its examples to be nonconforming, especially if an edit is in the works.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class="">&gt; Your utility requires the point instantiation of the friend function to
be before the point of use. Otherwise, it wouldn’t be in scope. However,
there is no point of instantiation defined for friends at all. You’re
relying on friends being treated like classes, not like other functions,
which seems especially brittle.<br class=""><br class=""></div>This is not entirely true, it requires the point of instantiation of the class-template specialization to be where it needs to be; </div></div></div></blockquote><div><br class=""></div><div>Calling the constexpr function requires its definition to precede the use. You’re assuming that the functions are defined by the class template instantiation: “Please note that the functions <code class="">func (short)</code> and <code class="">func (float)</code>
are <em class="">undefined</em> until <code class="">A&lt;short&gt;</code> and <code class="">A&lt;float&gt;</code> have been instantiated,
respectively.” This is not a safe assumption, because the point of instantiation may render the definition invisible to the current function.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">please note that default template-arguments are <b class="">not</b> part of the specialization itself, that means that `sizeof(...)` used as a default-argument to the template function effectively puts the instantiation of the relevant class prior to `main` (not prior to the instantiation of the function template specialization). The post "abuses" the instantiation of class template specializations, not function template specializations.<br class=""></div></div></div></blockquote><div><br class=""></div><div>I’m not sure what you mean by “prior to the instantiation of the function template specialization.” Points of instantiation are before or after non-template declarations at namespace scope. Classes come before, functions come after. Friends are unspecified, but they are functions, so we can extrapolate.</div><div><br class=""></div><div>Actually, constexpr function templates can’t usually form constant expressions at all according to the current rules. This needs a DR.</div></div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br>
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br>
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br>
<br><!--end of _originalContent --></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Discussion&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br />
David Krauss
2015-04-27 08:29:13 UTC
Permalink
‎No, two different specializations of the same template (of course).
My point is that the way you change state, by adding namespace-scope declarations, persists after the function definition. A second instantiation of the same function template specialization, as is always done automatically, will observe the changed state in a context where the first instantiation observed unchanged state. That’s ill-formed.

By the way, I have implemented a compile-time counter (http://stackoverflow.com/a/6174263/153285 <http://stackoverflow.com/a/6174263/153285> ) which does support counting inside functions, with a little elbow grease (http://coliru.stacked-crooked.com/a/f9840581681e3155 <http://coliru.stacked-crooked.com/a/f9840581681e3155> ). It’s safe for templates because the changes get reverted when you exit the local scope, which also renders the feature somewhat useless. Hence there’s no mention on the StackOverflow page. (Only the C++98 version has this capability.)
I think you are focusing on the wrong part; the instantiation order of the functions has nothing to do with the template default-arguments (which effectively instantiates the class template).. the template default-arguments are what is important.
I’m not talking about any components of your system, but its effect on a function template which might use it. The point is that it can only be used within non-template functions. You should note this in your article because it’s a major restriction.
In reply to the rest: the code is confirming, no edit is pending, there are cases where the order of function template instantiation matters - but the example provided is not one of them.
If you’re so confident, why ask for review in the first place?

Where in the standard does it say the compiler can’t process your function back-to-front and implement the compile-time state progress in reverse order, so in line 1 the function is defined and in line 2 it’s undefined? Both lines are in the same scope.
It is important to note that constexpr functions follow the same rules of normal functions,
As Richard just noted, you are depending on a proposed rule which is specific to constexpr function templates.
and just to make this even more clear one could also have expressed the method in the post by "abusing" default-arguments (non-template, regular arguments) since these expressions are said to be evaluated each time the function is invoked.
A default argument of a function template is a template in and of itself, equivalent to a function template, with a well-defined point of instantiation ([temp.inst] §14.7.1/13, [temp.point] §14.6.4.1/2). Default arguments need to produce consistent values wherever functions must.

The rules of default template argument evaluation are unspecified, as far as I know. It is merely common practice to evaluate them at each point of use, allowing different values at different uses. I hazily recall planning to file a DR long ago, but getting scared away because there’s a fair chance that the consensus will be more conservative: that different values shouldn’t be allowed. The simplest extrapolation from ordinary default arguments would suggest that default template arguments should be equivalent to constexpr function templates.

A default argument of an ordinary function, which seems to be what you’re getting at, can’t do anything interesting because it has no point of instantiation to make ADL aware of the context where it’s used. It gets compiled once and for all when it’s encountered in the function declarator.
The use of a template instead of a non-template is simply because the upcoming examples will be working with a similar concept (since that is shorter, but regular function default-arguments can accomplish the same thing).
You are in implementation-specific territory.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 08:44:09 UTC
Permalink
<html><head></head><body class="" style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">No, the "second" instantiation will use the template-parameters that are decided when the default-arguments are evaluated (this means that the "two" instantiations are the same, nothing ill-formed), ie. When the specialization is referenced.<br><br>The important part is that the template-parameters are decided when the implicit instantiation takes place, the default-arguments will only be evaluated once (at that time) (and such the meaning of the specialization remains the same no matter where the compiler generates the code for it)!<br><br>I hope the above explains what I mean, I'm currently on the subway and I get distracted quite easily.<br><br><br>I've also implemented a compile-time counter, and jftr everything the post (that this thread is about) talks about has already been implemented (and compiles with gcc, clang, msvc, and "somewhat" in ICC (because of the lack of proper support for constexpr in ICC).<br><br>Your implementation is very clever, and I'll be sure to let you know when the post including my compile-time counter (and container) has been posted.<br><br>I also want to thank you for taking time with posting on this very interesting topic!<br><br>/F</div> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br style="display:initial"></div> <div style="font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">::&nbsp;Filip&nbsp;Roséen&nbsp;(via&nbsp;BlackBerry)<br>::&nbsp;+46701448424&nbsp;<br>::&nbsp;***@gmail.com<br><br></div> <table width="100%" style="background-color:white;border-spacing:0px;"> <tbody><tr><td colspan="2" style="font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"> <div style="border-style: solid none none; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in 0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> <div><b>From: </b>David Krauss</div><div><b>Sent: </b>Monday, April 27, 2015 10:29 AM</div><div><b>To: </b>std-***@isocpp.org</div><div><b>Reply To: </b>std-***@isocpp.org</div><div><b>Subject: </b>Re: [std-discussion] non-constant constant-expressions, is it really possible?</div></div></td></tr></tbody></table><div style="border-style: solid none none; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"></div><br><div id="_originalContent" style=""><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On 2015–04–27, at 2:57 PM, Filip Roséen &lt;<a href="mailto:***@gmail.com" class="">***@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class="">‎<span style="font-size: initial; text-align: initial; line-height: initial;" class="">No, two different specializations of the same template (of course).</span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""></div></div></div></blockquote><div><br class=""></div><div>My point is that the way you change state, by adding namespace-scope declarations, persists after the function definition. A second instantiation of the same function template specialization, as is always done automatically, will observe the changed state in a context where the first instantiation observed unchanged state. That’s ill-formed.</div><div><br class=""></div><div>By the way, I have implemented a compile-time counter (<a href="http://stackoverflow.com/a/6174263/153285" class="">http://stackoverflow.com/a/6174263/153285</a>&nbsp;) which does support counting inside functions, with a little elbow grease (<a href="http://coliru.stacked-crooked.com/a/f9840581681e3155" class="">http://coliru.stacked-crooked.com/a/f9840581681e3155</a>&nbsp;). It’s safe for templates because the changes get reverted when you exit the local scope, which also renders the feature somewhat useless. Hence there’s no mention on the StackOverflow page. (Only the C++98 version has this capability.)</div><br class=""><blockquote type="cite" class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""><span style="font-family: sans-serif; line-height: initial; font-size: initial; text-align: initial;" class="">I think you are focusing on the wrong part; the instantiation order of the functions has nothing to do with the template default-arguments (which effectively instantiates the class template).. the template default-arguments are what is important.</span></div></div></blockquote><div><br class=""></div><div>I’m not talking about any components of your system, but its effect on a function template which might use it. The point is that it can only be used within non-template functions. You should note this in your article because it’s a major restriction.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""><span style="font-family: sans-serif; line-height: initial;" class="">In reply to the rest: the code is confirming, no edit is pending, there are cases where the order of function template instantiation matters - but the example provided is not one of them.<br class=""></span></div></div></div></blockquote><div><br class=""></div><div>If you’re so confident, why ask for review in the first place?</div><div><br class=""></div><div>Where in the standard does it say the compiler can’t process your function back-to-front and implement the compile-time state progress in reverse order, so in line 1 the function is defined and in line 2 it’s undefined? Both lines are in the same scope.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""><span style="font-family: sans-serif; line-height: initial; font-size: initial; text-align: initial;" class="">It is important to note that constexpr functions follow the same rules of normal functions, </span></div></div></div></blockquote><div><br class=""></div><div>As Richard just noted, you are depending on a proposed rule which is specific to constexpr function templates.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""><span style="font-family: sans-serif; line-height: initial; font-size: initial; text-align: initial;" class="">and just to make this even more clear one could also have expressed the method in the post by "abusing" default-arguments (non-template, regular arguments) since these expressions are said to be evaluated each time the function is invoked.</span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""></div></div></div></blockquote><div><br class=""></div><div>A default argument of a function template is a template in and of itself, equivalent to a function template, with a well-defined point of instantiation ([temp.inst] §14.7.1/13, [temp.point] §14.6.4.1/2). Default arguments need to produce consistent values wherever functions must.</div><div><br class=""></div><div>The rules of default template argument evaluation are unspecified, as far as I know. It is merely common practice to evaluate them at each point of use, allowing different values at different uses. I hazily recall planning to file a DR long ago, but getting scared away because there’s a fair chance that the consensus will be more conservative: that different values shouldn’t be allowed. The simplest extrapolation from ordinary default arguments would suggest that default template arguments should be equivalent to constexpr function templates.</div><div><br class=""></div><div><div>A default argument of an ordinary function, which seems to be what you’re getting at, can’t do anything interesting because it has no point of instantiation to make ADL aware of the context where it’s used. It gets compiled once and for all when it’s encountered in the function declarator.</div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div class="" style="background-color: rgb(255, 255, 255); line-height: initial;"><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);" class=""><span style="font-family: sans-serif; line-height: initial;" class="">The use of a template instead of a non-template is simply because the upcoming examples will be working with a similar concept (since that is shorter, but regular function default-arguments can accomplish the same thing).</span></div></div></div></blockquote><br class=""></div><div>You are in implementation-specific territory.</div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br>
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br>
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br>
<br><!--end of _originalContent --></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Discussion&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-discussion/">http://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br />
David Krauss
2015-04-27 10:00:55 UTC
Permalink
Post by Filip Roséen
No, the "second" instantiation will use the template-parameters that
Again, I’m not talking about the template f() or any other part of your utility. I’m talking about any function template which *uses* your utility.

The problem is absent from your examples, but you should still mention that your utility can’t be used within a (function) template.
Post by Filip Roséen
I hope the above explains what I mean, I'm currently on the subway and I get distracted quite easily.
I understand your program perfectly well. I’ve used all these tricks before, except for using noexcept to detect constant expressions. I’m also familiar with the frustration inherent in this area, the excitement and the disappointment. If you have a lot of StackOverflow reputation, you can even see a friend-based compile-time counter that I posted before arriving at the final answer linked earlier: http://stackoverflow.com/a/6166338/153285 <http://stackoverflow.com/a/6166338/153285> . (I was fortunate to have Johannes Schaub reviewing my work — we were competing to see who could solve the problem first.)
Post by Filip Roséen
I've also implemented a compile-time counter, and jftr everything the post (that this thread is about) talks about has already been implemented (and compiles with gcc, clang, msvc, and "somewhat" in ICC (because of the lack of proper support for constexpr in ICC).
Unfortunately, implementations are only weakly correlated with the theoretical ideal of the language. There are permissible things that no current implementation does, for example, concurrent processing of statements in a function. There are requirements that aren’t universally implemented, for example evaluating the unevaluated context of noexcept as a constant expression.

I hope you will stop to consider how much of the observed behavior is guaranteed by the standard.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 10:26:14 UTC
Permalink
Post by Filip Roséen
No, the "second" instantiation will use the template-parameters that
Again, I’m not talking about the template f() or any other part of your
utility. I’m talking about any function template which *uses* your utility.
The problem is absent from your examples, but you should still mention
that your utility can’t be used within a (function) template.
No worries, this will be mentioned in future posts because one needs to
know about those things in order to understand what doesn't, and more
importantly what does, work.

Maybe I misunderstood your intention, I thought you were talking about the
contents of the post specifically (not circumstances under which it might
not yield behavior which was never intended), you got a point - one has to
be very careful when dealing with these things.
Post by Filip Roséen
I hope the above explains what I mean, I'm currently on the subway and I
get distracted quite easily.
I understand your program perfectly well. I’ve used all these tricks
before, except for using noexcept to detect constant expressions. I’m
also familiar with the frustration inherent in this area, the excitement
and the disappointment. If you have a lot of StackOverflow reputation, you
can even see a friend-based compile-time counter that I posted before
http://stackoverflow.com/a/6166338/153285 . (I was fortunate to have
Johannes Schaub reviewing my work — we were competing to see who could
solve the problem first.)
I've spent fair share of time discussing things with litb (back when ##c++
@ freenode was.. different), and I do have "enough" reputation to look at
your post - no worries (and thanks for linking)!
Post by Filip Roséen
I've also implemented a compile-time counter, and jftr everything the post
(that this thread is about) talks about has already been implemented (and
compiles with gcc, clang, msvc, and "somewhat" in ICC (because of the lack
of proper support for constexpr in ICC).
Unfortunately, implementations are only weakly correlated with the
theoretical ideal of the language. There are permissible things that no
current implementation does, for example, concurrent processing of
statements in a function. There are requirements that aren’t universally
implemented, for example evaluating the unevaluated context of noexcept
as a constant expression.
I hope you will stop to consider how much of the observed behavior is
guaranteed by the standard.
The only thing I've done in my spare time during this last week is trying
to make sure that I only rely on things guaranteed by the standard, and I'm
being very careful not to make any false assumptions - and threads like
this certainly help me with that; so once again, thank you!
Post by Filip Roséen
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-04-27 13:00:52 UTC
Permalink
I now realize that my phone must have truncated some (or all) of the
messages I replied to in this thread, because when rereading it there are a
bunch of stuff which I didn't know got posted - and that is why I didn't
address them in previous messages; I deeply apologize for that. I'm
currently working on the upcoming post, which will include contents that
address some (if not all) of the points mentioned in this thread, once
again; thanks for keeping me on my feet!

Peace,
Post by Filip Roséen
Post by Filip Roséen
No, the "second" instantiation will use the template-parameters that
Again, I’m not talking about the template f() or any other part of your
utility. I’m talking about any function template which *uses* your utility.
The problem is absent from your examples, but you should still mention
that your utility can’t be used within a (function) template.
No worries, this will be mentioned in future posts because one needs to
know about those things in order to understand what doesn't, and more
importantly what does, work.
Maybe I misunderstood your intention, I thought you were talking about the
contents of the post specifically (not circumstances under which it might
not yield behavior which was never intended), you got a point - one has to
be very careful when dealing with these things.
Post by Filip Roséen
I hope the above explains what I mean, I'm currently on the subway and I
get distracted quite easily.
I understand your program perfectly well. I’ve used all these tricks
before, except for using noexcept to detect constant expressions. I’m
also familiar with the frustration inherent in this area, the excitement
and the disappointment. If you have a lot of StackOverflow reputation, you
can even see a friend-based compile-time counter that I posted before
http://stackoverflow.com/a/6166338/153285 . (I was fortunate to have
Johannes Schaub reviewing my work — we were competing to see who could
solve the problem first.)
I've spent fair share of time discussing things with litb (back when
look at your post - no worries (and thanks for linking)!
Post by Filip Roséen
I've also implemented a compile-time counter, and jftr everything the
post (that this thread is about) talks about has already been implemented
(and compiles with gcc, clang, msvc, and "somewhat" in ICC (because of the
lack of proper support for constexpr in ICC).
Unfortunately, implementations are only weakly correlated with the
theoretical ideal of the language. There are permissible things that no
current implementation does, for example, concurrent processing of
statements in a function. There are requirements that aren’t universally
implemented, for example evaluating the unevaluated context of noexcept
as a constant expression.
I hope you will stop to consider how much of the observed behavior is
guaranteed by the standard.
The only thing I've done in my spare time during this last week is trying
to make sure that I only rely on things guaranteed by the standard, and I'm
being very careful not to make any false assumptions - and threads like
this certainly help me with that; so once again, thank you!
Post by Filip Roséen
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-05-16 02:27:02 UTC
Permalink
Core issue 2118 Stateful metaprogramming via friend injection: We will make it ill-formed.
I might write a paper attempting to sway this position, but I don’t really think the mission is very hopeful. Also, I can’t guarantee that the use case I’d present would help with the one in this thread.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-05-16 06:32:43 UTC
Permalink
Are those publicly available yet?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-05-16 06:37:02 UTC
Permalink
Post by Nicol Bolas
Are those publicly available yet?
They’re on the Wiki.

I don’t really understand the permissions scheme there. Is the password supposed to be private or just a measure against spam?

Sorry if I divulged some secret :P .
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-05-16 12:43:22 UTC
Permalink
I don’t really understand the permissions scheme there. Is the password
supposed to be private or just a measure against spam?
It's not supposed to be distributed to the public at large.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
herb.sutter
2015-05-16 13:53:58 UTC
Permalink
Post by Ville Voutilainen
Post by David Krauss
I don’t really understand the permissions scheme there. Is the password
supposed to be private or just a measure against spam?
It's not supposed to be distributed to the public at large.
Right, the wiki password is not public (one might add, "by definition").
Also, we usually don't quote from the wiki notes because they are
unofficial and not vetted for complete accuracy; they are the subgroup's
scribes' best efforts to jot down the discussion as it happens.

The official progress on all issues is always made publicly available via
the issues lists, which are posted shortly after the meeting. In this case,
in a few days you'll see the updated post-Lenexa Core issues list, and you
can check it for the actual state of Core 2118 (and other issues). This is
the authoritative list to refer to.

Herb
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
d***@gmail.com
2016-08-16 15:48:24 UTC
Permalink
Did Core issue 2118 die? It's still listed as open more than a year later
and I can't find any updates to it.
Post by herb.sutter
Post by Ville Voutilainen
Post by David Krauss
I don’t really understand the permissions scheme there. Is the password
supposed to be private or just a measure against spam?
It's not supposed to be distributed to the public at large.
Right, the wiki password is not public (one might add, "by definition").
Also, we usually don't quote from the wiki notes because they are
unofficial and not vetted for complete accuracy; they are the subgroup's
scribes' best efforts to jot down the discussion as it happens.
The official progress on all issues is always made publicly available via
the issues lists, which are posted shortly after the meeting. In this case,
in a few days you'll see the updated post-Lenexa Core issues list, and you
can check it for the actual state of Core 2118 (and other issues). This is
the authoritative list to refer to.
Herb
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Filip Roséen
2015-05-27 19:30:09 UTC
Permalink
If you would like to co-author such paper I would be happy to contribute,
there are a few more quirks in the standard that allows one to reach the
same "goal" without using friend-injection.

I'm currently working on the 3rd part of the series of articles on
b.atch.se, the 4th one will address all "issues" that I know at the current
time of writing, and proposed resolution if one really wants them all to be
ill-formed. Given the fact that there is a lot of wording to be changed,
and that it could potentially kill already widely used implementations of
other (non-related) thingies, there might be a possibility to sway the
current opinion of the CWG.

Thanks for the update, much appreciated!

Best Regards,
Filip Roséen
Core issue 2118 Stateful metaprogramming via friend injection: We will make it ill-formed.
I might write a paper attempting to sway this position, but I don’t really
think the mission is very hopeful. Also, I can’t guarantee that the use
case I’d present would help with the one in this thread.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Krauss
2015-05-27 22:23:46 UTC
Permalink
If you would like to co-author such paper I would be happy to contribute, there are a few more quirks in the standard that allows one to reach the same "goal" without using friend-injection.
I’m thinking of elaborated-type-specifiers. Is there yet another one?

The committee justifiably tries to be conservative about what usage is valid. I have avoided bringing these techniques to their attention because it’s hard to put a positive spin. Likewise to the greater public.

We can collaborate on a paper :) . I’m not yet committed to writing anything. Relying on NDR is good enough for me, for now. I don’t think implementations are going to start detecting this anytime soon, whatever the committee decides. I’ve never released such code into the wild, and not likely to do so, although my use-case is quite practical, and necessary for the problem it solves.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Loading...