Topic: C++0x - a quick and dirty introduction (as of November 2007)
Author: Jerry Coffin <jcoffin@taeus.com>
Date: Thu, 20 Dec 2007 12:52:40 CST Raw View
In article <wZ6dnXDYfJjESvvanZ2dnUVZ_uyinZ2d@comcast.com>,
walter@digitalmars-nospamm.com says...
> Gabriel Dos Reis wrote:
> > The original generalized constant expression proposal did not
> > introduce a new keyword. However, feedback (expressed either through
> > emails or in face to face presentations and discussions) overwhelmingly
> > asked for a new keyword to precisely help both users and implementers.
> > And it actually did enhance the semantics.
> >
> > Users want to check up front when their functions are assured to be
> > constexpr, instead of blowing later in third party programs or libraries.
> >
> > Implementers want to know up front when they have to treat a given
> > function specially -- remember that function calls in general are NOT
> > constant expressions so many implementations take short circuits while
> > *parsing*.
> >
> >
> > There are other subtile points where a keyword helps ensure the proper
> > semantics -- discussed in detail in the constexpr proposal.
>
> Ok, I think I see the problem now. Given:
> static int x = foo();
> the C++ compiler has no clue whether foo() should be evaluated at
> compile time or run time. In the general case, it is not possible for
> the compiler to determine if foo() should be done at compile time or not
> (recursion depth, execution time is not statically predictable).
I, at least, see the problem somewhat differently. Let's look at a
typical case: I'm writing a function, and somebody else is using that
function. I start by writing a trivial stub:
int foo() { return 10; }
they can now do development against my stub. Now, somebody else writes
his code using this:
int array[foo()];
Under your rules, the compiler looks at foo(), sees that it can evaluate
it at compile time, so his code works.
Now, I create a somewhat closer to real version of foo():
int foo() {
return atoi(_argv[1]);
}
Now foo canNOT be evaluated at compile time, and all the code that
depends on that is broken. I need a way to specify the requirements my
function meets -- and the compiler should never assume it meets any more
requirements than it specifies, even if its current implementation might
be able to do so.
--
Later,
Jerry.
The universe is a figment of its own imagination.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Michael Fawcett <michael.fawcett@gmail.com>
Date: Thu, 20 Dec 2007 12:51:49 CST Raw View
On Dec 19, 10:03 pm, jgott...@carolina.rr.com (Joe Gottman) wrote:
> The question here is how recursive is recursive? We might define
> the above min function as follows:
>
> template <class X> inline constexpr X min(X first, X second, X... rest)
> {
> return min( ((b < a) ? b : a), rest...);
>
> }
>
> template <class X> inline constexpr X min(X first) {return first;}
I've seen this particular implementation twice now, once on the boost
ML and now here. Why don't you just terminate the recursion on the 2
argument version of min rather than introducing the rather odd one
argument version into the namespace?
e.g.
namespace boost
{
using std::min;
template <typename T, typename... Args>
const T &min(const T &a, const T &b, const Args &...args) {
return std::min(a, min(b, args...));
}
}
--Michael Fawcett
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Walter Bright <walter@digitalmars-nospamm.com>
Date: Thu, 20 Dec 2007 13:38:23 CST Raw View
Jerry Coffin wrote:
> Now foo canNOT be evaluated at compile time, and all the code that
> depends on that is broken. I need a way to specify the requirements my
> function meets -- and the compiler should never assume it meets any more
> requirements than it specifies, even if its current implementation might
> be able to do so.
I understand what you're asking for, but I don't regard it as a big
problem because it's not like your code will compile but fail at
runtime. It just won't compile, and the reason it won't compile will be
obvious.
The requirement that the compiler statically prove that constexpr
functions are executable at compile time for all possible parameter
values is very restrictive on the forms the function can take, otherwise
one has the famous halting problem.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Walter Bright <walter@digitalmars-nospamm.com>
Date: Thu, 20 Dec 2007 18:56:15 CST Raw View
Gabriel Dos Reis wrote:
> On Wed, 19 Dec 2007, Walter Bright wrote:
> | 2) I very much like to be able to look at initializations and see if they will
> | be done at compile time or runtime without having to poke through (potentially
> | voluminous) headers.
>
> I understand your like, but that hardly qualifies as an argument to
> deam something `an obsolete feature'.
While I phrased it badly, this is a problem with the auditability of C++
code. Auditability is the ability of code reviewers to examine the code
and check it for correctness. Seeing a local static initialization and
knowing if it is thread safe or not is a very difficult task. The
reviewer would probably have to resort to looking at a disassembly of
the code.
There are many aspects of C++ that impair auditability, which is why the
following are growth industries:
1) proliferation of compiler warnings
2) lint
3) coverity
4) coding standards documents
These things are rich sources of inspiration for how to improve the core
language. Here's one example: in one C++ coding standards spec, the use
of the integer literal postfix 'l' was proscribed because in many fonts
101 and 10l are indistinguishable. Therefore, in the D programming
language, 'l' is not a valid suffix (use 'L' instead). A simple change
to the language, and there's no longer an issue - one doesn't have to
put it in a coding standard, yell at your employees to stop using 'l',
hack it into a lint program, etc. The problem is just defined out of
existence.
> | 3) Dynamic initialization of local statics introduces multithreading issues.
> | This can be dealt with by the compiler always using a mutex, which introduces
> | bloat all over the place, or optional mutexes with a compiler switch leading
> | to bloat or overlooked bugs, or using a simple static one-shot which suffers
> | from race conditions that aren't at all obvious from code inspection.
>
> Is there evidence that letting all programmers systematically dealing
> with that task lead to more correct, more maintainable code?
>
> As I understand it, C++ programmers have the choice of using OR not
> using dynamic initialization of local statics.
Right, and I never use it. The underlying issue is being able to tell if
it was happening or not, just like the ROMable issue for global statics.
Then, if it is happening, is it thread-safe.
Sure, such can possibly be avoided with coding conventions. But learning
C++ seems to occur in two phases - 1) learn the language, then, 2) learn
all the conventions that have evolved over time to head off disastrous
problems.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: jdennett@acm.org (James Dennett)
Date: Fri, 21 Dec 2007 16:28:54 GMT Raw View
Walter Bright wrote:
> Jerry Coffin wrote:
>> Now foo canNOT be evaluated at compile time, and all the code that
>> depends on that is broken. I need a way to specify the requirements my
>> function meets -- and the compiler should never assume it meets any
>> more requirements than it specifies, even if its current
>> implementation might be able to do so.
>
> I understand what you're asking for, but I don't regard it as a big
> problem because it's not like your code will compile but fail at
> runtime. It just won't compile, and the reason it won't compile will be
> obvious.
And can _still_ be a big problem. The vendor whose library you used
changed it in a new release (which you need because of fixes or new
features), and now your code doesn't work with it. The changes needed
may be extensive. And it could have been avoided if you'd used C++0x
instead of D, because the compile-time constant nature of the function
would have been a compiler-enforced part of its explicit *interface*,
not just a mutable artifact of its implementation.
> The requirement that the compiler statically prove that constexpr
> functions are executable at compile time for all possible parameter
> values is very restrictive on the forms the function can take, otherwise
> one has the famous halting problem.
Right. A compile-time language ought not to be Turing complete,
even if only because of resource limitations.
-- James
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Fri, 21 Dec 2007 11:18:09 CST Raw View
On Dec 20, 9:51 pm, Michael Fawcett <michael.fawc...@gmail.com> wrote:
> I've seen this particular implementation twice now, once on the boost
> ML and now here. Why don't you just terminate the recursion on the 2
> argument version of min rather than introducing the rather odd one
> argument version into the namespace?
So that functions with variadic template arguments can just apply
min() to the whole pack, even if there is only a single argument in
there.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Michael Fawcett <michael.fawcett@gmail.com>
Date: Fri, 21 Dec 2007 12:21:00 CST Raw View
On Dec 21, 12:18 pm, int...@gmail.com wrote:
> On Dec 20, 9:51 pm, Michael Fawcett <michael.fawc...@gmail.com> wrote:
>
> > I've seen this particular implementation twice now, once on the boost
> > ML and now here. Why don't you just terminate the recursion on the 2
> > argument version of min rather than introducing the rather odd one
> > argument version into the namespace?
>
> So that functions with variadic template arguments can just apply
> min() to the whole pack, even if there is only a single argument in
> there.
How does my implementation not take that into account also? It's more
lines of code to introduce the one argument version, and it's also
just weird to have that version hanging around. There exists a much
more elegant solution, and I believe the one I posted is it.
--Mike
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Michael Fawcett <michael.fawcett@gmail.com>
Date: Fri, 21 Dec 2007 15:48:31 CST Raw View
On Dec 21, 12:18 pm, int...@gmail.com wrote:
> On Dec 20, 9:51 pm, Michael Fawcett <michael.fawc...@gmail.com> wrote:
>
> > I've seen this particular implementation twice now, once on the boost
> > ML and now here. Why don't you just terminate the recursion on the 2
> > argument version of min rather than introducing the rather odd one
> > argument version into the namespace?
>
> So that functions with variadic template arguments can just apply
> min() to the whole pack, even if there is only a single argument in
> there.
Sorry, in my original reply I misunderstood you. Now I think I see
what you mean. For instance, something like:
template <typename T, typename... Args>
T some_math(T a, T b, const Args &... args) {
return a + b + min(args...);
}
I hadn't considered a use case like that. I still think it's odd to
introduce the single argument version of min. The only time it makes
sense is when accepting an argument pack. For regular variables it's
"just weird":
int a = 10;
int b = std::min(a); // why would we even provide this?
You could transform the code from the "some_math" use-case above into
two functions, one that takes 3 parameters, and one that takes a
variadic template as the third, but that does seem like a burden on
the implementer.
template <typename T>
T some_math(T a, T b, T c) {
return a + b + c;
}
template <typename T, typename... Args>
T some_math(T a, T b, const Args &... args) {
return a + b + min(args...);
}
Then you could get away with my original variadic min code that
terminates on the 2 argument version of min.
I don't have enough variadic template experience to say what's best,
but I guess I will just reiterate that terminating the variadic min
function with a one argument version that will be available to users
is a little weird IMVHO.
--Michael Fawcett
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Michael Fawcett <michael.fawcett@gmail.com>
Date: Sat, 22 Dec 2007 01:19:40 CST Raw View
On Dec 21, 4:48 pm, Michael Fawcett <michael.fawc...@gmail.com> wrote:
>
> template <typename T>
> T some_math(T a, T b, T c) {
> return a + b + c;}
>
> template <typename T, typename... Args>
> T some_math(T a, T b, const Args &... args) {
> return a + b + min(args...);
>
> }
Argh! Of course I meant:
template <typename T, typename... Args>
T some_math(T a, T b, T c, const Args &... args) {
return a + b + min(c, args...);
}
Sorry,
--Michael Fawcett
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Sun, 23 Dec 2007 04:34:32 GMT Raw View
James Dennett wrote:
> Walter Bright wrote:
>> Jerry Coffin wrote:
>>> Now foo canNOT be evaluated at compile time, and all the code
>>> that depends on that is broken. I need a way to specify the
>>> requirements my function meets -- and the compiler should never
>>> assume it meets any more requirements than it specifies, even if
>>> its current implementation might be able to do so.
>> I understand what you're asking for, but I don't regard it as a big
>> problem because it's not like your code will compile but fail at
>> runtime. It just won't compile, and the reason it won't compile
>> will be obvious.
>
> And can _still_ be a big problem. The vendor whose library you used
> changed it in a new release (which you need because of fixes or new
> features), and now your code doesn't work with it. The changes
> needed may be extensive.
There's an awful lot more to contract programming than constexpr
provides, very little of which is supported by C++ (I think the contract
programming proposal was rejected). Even that is no guarantee that
library semantic changes won't break existing code. For example, C++
doesn't support the 'out' parameter storage class, where the function is
obligated to initialize the argument. C++ does support
pass-by-reference, but there is no semantic clue if it is in-out or out.
Even worse, constexpr actively prevents the library implementor from
adding any argument checking code to it. Constexpr functions will suffer
from atoi's well-known deficiency:
"When atoi encounters a string with no numerical sequence, it returns a
0 (zero). Also, if the string holds a valid sequence of digits that
represents the number 0, it would also return a 0, making it impossible
to tell from the return value alone whether the string held a valid
number or not. The newer function strtol does not have this deficiency."
-- http://en.wikipedia.org/wiki/Atoi
> And it could have been avoided if you'd used C++0x instead of D,
> because the compile-time constant nature of the function would have
> been a compiler-enforced part of its explicit *interface*, not just a
> mutable artifact of its implementation.
>
>> The requirement that the compiler statically prove that constexpr
>> functions are executable at compile time for all possible parameter
>> values is very restrictive on the forms the function can take,
>> otherwise one has the famous halting problem.
>
> Right. A compile-time language ought not to be Turing complete, even
> if only because of resource limitations.
What that means is that constexpr functions cannot throw exceptions,
cannot have reference parameters, cannot do recursion, and cannot do
iteration. People who need to do non-trivial computations at compile
time will be forced back to using template metaprogramming, which
(horrific as it is) is Turing complete. Or they'll stick to using the
macro preprocessor, which is also Turing complete.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Tue, 18 Dec 2007 01:19:12 CST Raw View
On Mon, 17 Dec 2007, Walter Bright wrote:
| The D programming language solves the problem from the opposite direction than
| C++ does. It is always determinable, from the context, whether foo() should be
| evaluated at compile time or run time. For example,
| static int x = foo();
| is always evaluated at compile time, since dynamic initializers for static
| variables are not allowed (such belong in the static constructor).
Yes, a `solution' to the problem can be `just ban'.
However, banning dynamic initializers for static variables isn't a
viable option in the context of C++ now.
| This implies, of course, that:
| static const int x = foo();
| is unambiguously ROMable.
As is
static constexpr int x = foo();
in C++0x.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Tue, 18 Dec 2007 01:19:16 CST Raw View
On Mon, 17 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
| Joe Gottman wrote:
| > Walter Bright wrote:
| > > James Kanze wrote:
| > > > I'm not arguing against making more things available as compile
| > > > time constants. I'm just saying that the programmer should be
| > > > able to express his intent, to avoid thing accidentally getting
| > > > used as compile time constants when he doesn't want to guarantee
| > > > that as part of the contract.
| > >
| > > I understand your point, but since a compile time error is issued if
| > > anything goes wrong, I don't see a big issue.
| > >
| >
| > Suppose I'm writing some code, and a variable just happens to be a
| > compile-time constant without my planning this. Another programmer uses the
| > compile-time constant in his code. I never see his code so I don't know
| > that this is an issue. If I later modify my code so that the variable isn't
| > a compile-time constant then I end up accidentally breaking the other
| > programmer's code.
|
| This is happening today in C++ and I'm not seeing a problem with that:
| statically-initialized and dynamically-initialized static constant data have
| the same static type.
The `constexpr' keyword lets users to specify that they want a global
constant objects be statically initialized -- or else diagnostic.
Lacking proper linguistic support to say that today has been reported to
cause surprises.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Tue, 18 Dec 2007 17:12:28 GMT Raw View
Gabriel Dos Reis wrote:
> On Mon, 17 Dec 2007, Walter Bright wrote:
>
> | The D programming language solves the problem from the opposite direction than
> | C++ does. It is always determinable, from the context, whether foo() should be
> | evaluated at compile time or run time. For example,
> | static int x = foo();
> | is always evaluated at compile time, since dynamic initializers for static
> | variables are not allowed (such belong in the static constructor).
>
> Yes, a `solution' to the problem can be `just ban'.
> However, banning dynamic initializers for static variables isn't a
> viable option in the context of C++ now.
I understand, but at some point, I think C++ will seriously have to look
at obsolete features and consider them for removal in order to allow the
language to modernize.
> | This implies, of course, that:
> | static const int x = foo();
> | is unambiguously ROMable.
>
> As is
>
> static constexpr int x = foo();
>
> in C++0x.
There isn't any language design problem that cannot be solved by one of:
1) adding another keyword
2) adding an overload of 'static'
<g>
But I wonder what the future will be for constexpr functions. I think
it's possible that we may see that such functions are defined twice,
once with constexpr and once without. This is because the suitability of
a function for CTFE may often be dependent on its particular argument
values.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: richard.corden@gmail.com (Richard Corden)
Date: Tue, 18 Dec 2007 17:12:42 GMT Raw View
Andrei Alexandrescu (See Website For Email) wrote:
> Joe Gottman wrote:
[...]
>> If I later modify my code so that
>> the variable isn't a compile-time constant then I end up accidentally
>> breaking the other programmer's code.
>
> This is happening today in C++ and I'm not seeing a problem with that:
> statically-initialized and dynamically-initialized static constant data
> have the same static type.
It's not a perfect analogy, today programs continue to compile for the
static/dynamic initialization case. A change from static to dynamic
initialization will change behaviour for some subset of existing
programs, the constexpr case would result in 100% of programs not compiling.
Richard
--
Richard Corden
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Wed, 19 Dec 2007 05:01:00 GMT Raw View
On Tue, 18 Dec 2007, Walter Bright wrote:
| But I wonder what the future will be for constexpr functions. I think it's
| possible that we may see that such functions are defined twice, once with
| constexpr and once without. This is because the suitability of a function for
| CTFE may often be dependent on its particular argument values.
Could you clarify that?
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Wed, 19 Dec 2007 05:15:55 GMT Raw View
On Tue, 18 Dec 2007, Walter Bright wrote:
| Gabriel Dos Reis wrote:
| > On Mon, 17 Dec 2007, Walter Bright wrote:
| >
| > | The D programming language solves the problem from the opposite direction
| > | than
| > | C++ does. It is always determinable, from the context, whether foo()
| > | should be
| > | evaluated at compile time or run time. For example,
| > | static int x = foo();
| > | is always evaluated at compile time, since dynamic initializers for static
| > | variables are not allowed (such belong in the static constructor).
| >
| > Yes, a `solution' to the problem can be `just ban'.
| > However, banning dynamic initializers for static variables isn't a
| > viable option in the context of C++ now.
|
| I understand, but at some point, I think C++ will seriously have to look at
| obsolete features and consider them for removal in order to allow the language
| to modernize.
Why do you consider dynamic initialization of global or static objects an
obsolete feature?
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Walter Bright <walter@digitalmars-nospamm.com>
Date: Wed, 19 Dec 2007 01:29:02 CST Raw View
Gabriel Dos Reis wrote:
> On Tue, 18 Dec 2007, Walter Bright wrote:
>
> | Gabriel Dos Reis wrote:
> | > On Mon, 17 Dec 2007, Walter Bright wrote:
> | >
> | > | The D programming language solves the problem from the opposite direction
> | > | than
> | > | C++ does. It is always determinable, from the context, whether foo()
> | > | should be
> | > | evaluated at compile time or run time. For example,
> | > | static int x = foo();
> | > | is always evaluated at compile time, since dynamic initializers for static
> | > | variables are not allowed (such belong in the static constructor).
> | >
> | > Yes, a `solution' to the problem can be `just ban'.
> | > However, banning dynamic initializers for static variables isn't a
> | > viable option in the context of C++ now.
> |
> | I understand, but at some point, I think C++ will seriously have to look at
> | obsolete features and consider them for removal in order to allow the language
> | to modernize.
>
> Why do you consider dynamic initialization of global or static objects an
> obsolete feature?
Because:
1) its shortcomings have produced the need for another storage class,
'constexpr', as discussed here.
2) I very much like to be able to look at initializations and see if
they will be done at compile time or runtime without having to poke
through (potentially voluminous) headers. One of the first design
decisions of the D programming language was to scrap dynamic
initializers for static data. Dynamic initializers go into clearly
marked static constructors, instead of being implied.
3) Dynamic initialization of local statics introduces multithreading
issues. This can be dealt with by the compiler always using a mutex,
which introduces bloat all over the place, or optional mutexes with a
compiler switch leading to bloat or overlooked bugs, or using a simple
static one-shot which suffers from race conditions that aren't at all
obvious from code inspection.
4) C++ leaves undefined the order of inter-module static construction,
which is simply unacceptable from a QA standpoint. Having the dynamic
construction collected together in a static constructor at least gives
the QA engineer an identifiable place to look for ordering problems.
5) Collecting the dynamic initializers into a static constructor enables
the intra-module order of construction to be controlled independently of
the definition order.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Wed, 19 Dec 2007 07:29:10 GMT Raw View
Walter Bright wrote:
> But I wonder what the future will be for constexpr functions. I think
> it's possible that we may see that such functions are defined twice,
> once with constexpr and once without. This is because the suitability of
> a function for CTFE may often be dependent on its particular argument
> values.
>
I don't think this is a problem. If a parameter that is not a
compile-time constant is passed into a constexpr function then the
result compiles but is not a compile time constant. Thus
constexpr int square(constexpr int x) {return x * x;}
int x1 = square(3); // square evaluated at compile time.
int y = 7; // Not a constant.
int x2 = square(y); // square evaluated at run time.
Joe Gottman
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Wed, 19 Dec 2007 15:08:38 GMT Raw View
Gabriel Dos Reis wrote:
> On Tue, 18 Dec 2007, Walter Bright wrote:
>
> | But I wonder what the future will be for constexpr functions. I think it's
> | possible that we may see that such functions are defined twice, once with
> | constexpr and once without. This is because the suitability of a function for
> | CTFE may often be dependent on its particular argument values.
>
> Could you clarify that?
Sure. Suppose I have a square root function:
double sqrt(double d)
{
if (d < 0)
throw new SquareRootException();
... compute square root ...
return root;
}
If the language requires that I say, for all possible values of d, this
must be evaluatable at compile time, I've got a problem. So, instead I'd
have to write two functions:
double sqrt(double d)
{
if (d < 0)
throw new SquareRootException();
... compute square root ...
return root;
}
constexpr double sqrtx(double d)
{
... compute square root ...
return root;
}
This can be characterized as different argument values taking different
paths through the functions, some of which may be evaluatable at compile
time and some not.
There are other cases like, for example, some argument values may take
unreasonably long to execute at compile time, but only a short time at
runtime.
In other words, I think the decision to run at compile time or at run
time is properly put at the call site, not the definition site.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Wed, 19 Dec 2007 11:38:18 CST Raw View
On Dec 19, 6:08 pm, wal...@digitalmars-nospamm.com (Walter Bright)
wrote:
> Sure. Suppose I have a square root function:
>
> double sqrt(double d)
> {
> if (d < 0)
> throw new SquareRootException();
> ... compute square root ...
> return root;
>
> }
>
> If the language requires that I say, for all possible values of d, this
> must be evaluatable at compile time, I've got a problem. So, instead I'd
> have to write two functions:
>
> double sqrt(double d)
> {
> if (d < 0)
> throw new SquareRootException();
> ... compute square root ...
> return root;
>
> }
>
> constexpr double sqrtx(double d)
> {
> ... compute square root ...
> return root;
>
> }
No, not really. If I read the proposal correctly, you can perfectly
well write:
constexpr double sqrt(double d)
{
return d > 0 ? (compute square root) : ((throw domain_error()),
0);
}
If you call sqrt with a valid argument, it produces a compile-time
constant. If you do not, it won't. I.e.:
int n[sqrt(1)]; // ok
int n[sqrt(-1)]; // error, not a compile-time constant
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Wed, 19 Dec 2007 12:06:08 CST Raw View
On Wed, 19 Dec 2007, Walter Bright wrote:
| Gabriel Dos Reis wrote:
| > On Tue, 18 Dec 2007, Walter Bright wrote:
| >
| > | Gabriel Dos Reis wrote:
| > | > On Mon, 17 Dec 2007, Walter Bright wrote:
| > | >
| > | > | The D programming language solves the problem from the opposite
| > | > | direction
| > | > | than
| > | > | C++ does. It is always determinable, from the context, whether foo()
| > | > | should be
| > | > | evaluated at compile time or run time. For example,
| > | > | static int x = foo();
| > | > | is always evaluated at compile time, since dynamic initializers for
| > | > | static
| > | > | variables are not allowed (such belong in the static constructor).
| > | >
| > | > Yes, a `solution' to the problem can be `just ban'.
| > | > However, banning dynamic initializers for static variables isn't a
| > | > viable option in the context of C++ now.
| > |
| > | I understand, but at some point, I think C++ will seriously have to look
| > | at
| > | obsolete features and consider them for removal in order to allow the
| > | language
| > | to modernize.
| >
| > Why do you consider dynamic initialization of global or static objects an
| > obsolete feature?
|
| Because:
|
| 1) its shortcomings have produced the need for another storage class,
| 'constexpr', as discussed here.
The primary reason for having `constexpr' as discussed earlier, is
because people want to have early diagnostics and implementers want to
know when they have to treat something specially.
Although `constexpr' also serves to enforce static initialization, it
wasn't primarily motivated by that.
Consequently, I do not believe it is correct to state that `dynamic
initialization' of global/statics has produced the need of constexpr.
| 2) I very much like to be able to look at initializations and see if they will
| be done at compile time or runtime without having to poke through (potentially
| voluminous) headers.
I understand your like, but that hardly qualifies as an argument to
deam something `an obsolete feature'.
| 3) Dynamic initialization of local statics introduces multithreading issues.
| This can be dealt with by the compiler always using a mutex, which introduces
| bloat all over the place, or optional mutexes with a compiler switch leading
| to bloat or overlooked bugs, or using a simple static one-shot which suffers
| from race conditions that aren't at all obvious from code inspection.
Is there evidence that letting all programmers systematically dealing
with that task lead to more correct, more maintainable code?
As I understand it, C++ programmers have the choice of using OR not
using dynamic initialization of local statics.
| 4) C++ leaves undefined the order of inter-module static construction, which
That does not make the feature itself obsolete.
| is simply unacceptable from a QA standpoint. Having the dynamic construction
| collected together in a static constructor at least gives the QA engineer an
| identifiable place to look for ordering problems.
|
| 5) Collecting the dynamic initializers into a static constructor enables the
| intra-module order of construction to be controlled independently of the
| definition order.
But again, that does not make the feature obsolete.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Wed, 19 Dec 2007 12:04:41 CST Raw View
On Dec 15, 5:46 am, bjarne <bja...@gmail.com> wrote:
> I don't see implementation as a key problem. My problem is with the
> (lack of) quality of the examples of need for recursive constexpr.
Wouldn't essentially any existing C++ program that uses template
recursion to calculate values (as opposed to types) at compile time
qualify? I'm sure we can find some examples of that in Boost.
Also, what about constexpr functions with variadic template arguments?
What is the correct way to write any such in the absence of recursion?
A good example is N2485, the recent variadic std::min proposal:
sematically, it's a pure function, and so clearly should be
constexpr.Yet its definition in the paper is recursive.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Wed, 19 Dec 2007 18:47:35 GMT Raw View
int19h@gmail.com wrote:
> No, not really. If I read the proposal correctly, you can perfectly
> well write:
>
> constexpr double sqrt(double d)
> {
> return d > 0 ? (compute square root) : ((throw domain_error()),
> 0);
> }
>
> If you call sqrt with a valid argument, it produces a compile-time
> constant. If you do not, it won't. I.e.:
>
> int n[sqrt(1)]; // ok
> int n[sqrt(-1)]; // error, not a compile-time constant
I'm not sure exactly what the proposal says about this, but my
impression from this thread was that applying constexpr to a function
was requiring that function to produce a compile time result for all
possible parameter values, i.e. it was a 'contract' imposing a
requirement on the function.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Wed, 19 Dec 2007 13:51:29 CST Raw View
On 19 Dec, 21:47, wal...@digitalmars-nospamm.com (Walter Bright)
wrote:
> I'm not sure exactly what the proposal says about this, but my
> impression from this thread was that applying constexpr to a function
> was requiring that function to produce a compile time result for all
> possible parameter values, i.e. it was a 'contract' imposing a
> requirement on the function.
It is, but it seems to be not so clear-cut as that. Here is the
contract for constexpr function, taken directly from the Standard:
- its return type shall be a literal type
- each of its parameter types shall be a literal type
- its function-body shall be a compound-statement of the form
{ return expression ; }
where expression is a potential constant expression
- every implicit conversion used in converting expression to the
function return type shall be one of those allowed in a constant
expression
I haven't found the definition of a "potential constant expression",
but "constant expression" itself is defined thus:
"A conditional-expression is a constant expression unless it involves
one of the following as a potentially evaluated subexpression, but
subexpressions of logical AND, logical OR, and conditional operations
that are not evaluated are not considered"
Then there follows a list of what may not appear in a constant
expression, which includes operator throw. However, the second part of
the above definition seems to say that an expression will still be
constant if the throw is in the non-evaluated branch of operator :?.
Whether such an expression, in which the condition part of operator ?:
depends on a free variable in a constexpr function, is a "potential
constant expression", is not exactly clear, but I think that was the
intent, otherwise the usefulness of this requirement is rather small.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Wed, 19 Dec 2007 15:33:02 CST Raw View
On 19 Dez., 19:04, int...@gmail.com wrote:
> On Dec 15, 5:46 am, bjarne <bja...@gmail.com> wrote:
> Also, what about constexpr functions with variadic template arguments?
> What is the correct way to write any such in the absence of recursion?
> A good example is N2485, the recent variadic std::min proposal:
> sematically, it's a pure function, and so clearly should be
> constexpr.Yet its definition in the paper is recursive.
I agree that most examples of variadic template arguments
will require a recursive solution due to the way we have
to decompose the argument sequence. Note that the variadic
min/max example will require that you provide two flavours:
1) One with by-ref arguments for the non-constexpr variant
2) One with by-value arguments for the constexpr variant.
For further details see:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#719
I also agree that I expect a natural tendency to combine
templates/variadic templates with constexpr functions and
that this combination will tend to recursive solutions, which
must necessarily stop at the constexpr function level (or
must provide the implementation via templates).
I would expect that it should be possible to compute the
to_ulong of a std::bitset via a recursive solution as a
constexpr, no?
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Walter Bright <walter@digitalmars-nospamm.com>
Date: Wed, 19 Dec 2007 17:08:56 CST Raw View
int19h@gmail.com wrote:
> Then there follows a list of what may not appear in a constant
> expression, which includes operator throw. However, the second part of
> the above definition seems to say that an expression will still be
> constant if the throw is in the non-evaluated branch of operator :?.
> Whether such an expression, in which the condition part of operator ?:
> depends on a free variable in a constexpr function, is a "potential
> constant expression", is not exactly clear, but I think that was the
> intent, otherwise the usefulness of this requirement is rather small.
I agree with your analysis of the spec. However, this makes constexpr as
a 'contract' placed on the function definition unenforceable (and hence
useless) because the compiler cannot statically determine which paths
will be taken until the functions are actually called.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Thu, 20 Dec 2007 03:03:16 GMT Raw View
int19h@gmail.com wrote:
> On Dec 15, 5:46 am, bjarne <bja...@gmail.com> wrote:
>> I don't see implementation as a key problem. My problem is with the
>> (lack of) quality of the examples of need for recursive constexpr.
>
> Wouldn't essentially any existing C++ program that uses template
> recursion to calculate values (as opposed to types) at compile time
> qualify? I'm sure we can find some examples of that in Boost.
>
> Also, what about constexpr functions with variadic template arguments?
> What is the correct way to write any such in the absence of recursion?
> A good example is N2485, the recent variadic std::min proposal:
> sematically, it's a pure function, and so clearly should be
> constexpr.Yet its definition in the paper is recursive.
>
>
The question here is how recursive is recursive? We might define
the above min function as follows:
template <class X> inline constexpr X min(X first, X second, X... rest)
{
return min( ((b < a) ? b : a), rest...);
}
template <class X> inline constexpr X min(X first) {return first;}
Now the expression min(1,2,3) calls the function min<int, int, int>
which calls min<int, int> which calls min<int>. It can be argued that
these are three different functions so no recursion occurs. If so, then
min(1,2,3) can be evaluated at compile time.
Joe Gottman
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Thu, 20 Dec 2007 12:48:11 CST Raw View
On 20 Dec, 02:08, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:
> int...@gmail.com wrote:
> > Then there follows a list of what may not appear in a constant
> > expression, which includes operator throw. However, the second part of
> > the above definition seems to say that an expression will still be
> > constant if the throw is in the non-evaluated branch of operator :?.
> > Whether such an expression, in which the condition part of operator ?:
> > depends on a free variable in a constexpr function, is a "potential
> > constant expression", is not exactly clear, but I think that was the
> > intent, otherwise the usefulness of this requirement is rather small.
>
> I agree with your analysis of the spec. However, this makes constexpr as
> a 'contract' placed on the function definition unenforceable (and hence
> useless) because the compiler cannot statically determine which paths
> will be taken until the functions are actually called.
Actually, I see now that I was mistaken. A "potential constant
expression" is defined in the spec in precisely the way you expected
it to be:
"An expression is a potential constant expression if it is a constant
expression when all occurrences of function parameters are replaced by
arbitrary constant expressions of the appropriate type."
So, you were correct that one cannot write a constexpr function with a
limited domain. Not even an extra overload would help, since there's
no proper way to signal contract violation for constexpr... a real
pity.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Sat, 15 Dec 2007 18:57:17 CST Raw View
On Dec 13, 11:00 pm, wal...@digitalmars-nospamm.com (Walter Bright)
wrote:
> James Kanze wrote:
> > If my intent is that the return value of the function can be
> > used as an integral constant expression, e.g. as an array
> > dimension, then you definitly want to say so somewhere.
> It's not necessary.
I didn't say it was necessary. I said it was desirable. The
compiler obviously knows whether it can evaluate something as a
function or not. It's necessary for program readability and
maintenance, however---I don't want client code using something
as a constant unless I'm willing to guarantee that it will be a
constant in future versions as well, as part of the contract.
> For example, to use it as an array dimension:
> int foo[factorial(3)];
> > For one thing, it's an essential part of the contract,
> I don't agree. If it cannot be evaluated at compile time, and
> you use it in a context where it must be, the compiler will
> tell you (issue an error message).
Yes, but by then, it's too late. The problem is something that
the compiler can evaluate as a contract, but only as an accident
of the current implementation, rather than because I guarantee
it. (It's also nice if I guarantee it, and the compiler can
tell me immediately that I've gone too far, rather that only
telling me so when I compile my tests.)
> Similarly,
> int x;
> int foo[x + 3];
> will produce an error message because x cannot be evaluated at
> compile time. A contract isn't necessary.
It isn't if you're just hacking code for your own use. It is if
anyone else is to use my code.
> Although D doesn't (yet) have the semantic notion of a 'pure'
> function, functions that are CTFE-capable must currently be a
> subset of pure functions.
> > In the case of C++, of course, calling
> > any function not defined in the current translation unit would
> > probably suffice to inhibit compile time evaluation.
> Of course, the compiler would need the function body available
> to it. But John Nagle has a point in that unless the core
> language has arrays in it so that arrays can be manipulated at
> compile time, CTFE capability may not be that useful. The D
> programming language has core strings, arrays, associative
> arrays, and tuples, enabling CTFE to shine.
I'm not arguing against making more things available as compile
time constants. I'm just saying that the programmer should be
able to express his intent, to avoid thing accidentally getting
used as compile time constants when he doesn't want to guarantee
that as part of the contract.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Walter Bright <walter@digitalmars-nospamm.com>
Date: Sat, 15 Dec 2007 22:37:54 CST Raw View
James Kanze wrote:
> I'm not arguing against making more things available as compile
> time constants. I'm just saying that the programmer should be
> able to express his intent, to avoid thing accidentally getting
> used as compile time constants when he doesn't want to guarantee
> that as part of the contract.
I understand your point, but since a compile time error is issued if
anything goes wrong, I don't see a big issue.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Sun, 16 Dec 2007 10:40:20 CST Raw View
On Dec 16, 5:37 am, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:
> James Kanze wrote:
> > I'm not arguing against making more things available as compile
> > time constants. I'm just saying that the programmer should be
> > able to express his intent, to avoid thing accidentally getting
> > used as compile time constants when he doesn't want to guarantee
> > that as part of the contract.
> I understand your point, but since a compile time error is issued if
> anything goes wrong, I don't see a big issue.
No it's not. If my function happens "accidentally" (i.e. I
don't want to guarantee it to be a constant as part of the
interface) to be a compile time constant, and someone uses it as
a constant, there will be no compile time error. If I later
change the function, and it ceases to be a compile time
constant, I've broken user code.
Admittedly, the code was actually broken before, since the user
used the function in a way that was not documented to work. But
as a vendor, I don't like breaking user code, even if the user
was wrong. Proving users to be stupid is NOT the best
commercial policy I can think of.
And no, it's not a "big" issue. It's probably not worth adding
a keyword to D, for example, to handle it. But since we're
talking about what C++ should or should not accept, and the new
keyword is already part of the proposal, it would seem a shame
not to use it.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Mon, 17 Dec 2007 06:49:31 GMT Raw View
Walter Bright wrote:
> James Kanze wrote:
>> I'm not arguing against making more things available as compile
>> time constants. I'm just saying that the programmer should be
>> able to express his intent, to avoid thing accidentally getting
>> used as compile time constants when he doesn't want to guarantee
>> that as part of the contract.
>
> I understand your point, but since a compile time error is issued if
> anything goes wrong, I don't see a big issue.
>
Suppose I'm writing some code, and a variable just happens to be a
compile-time constant without my planning this. Another programmer uses
the compile-time constant in his code. I never see his code so I don't
know that this is an issue. If I later modify my code so that the
variable isn't a compile-time constant then I end up accidentally
breaking the other programmer's code.
Joe Gottman
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: kwikius <andy@servocomm.freeserve.co.uk>
Date: Mon, 17 Dec 2007 01:00:03 CST Raw View
On 15 Dec, 02:46, bjarne <bja...@gmail.com> wrote:
> Based on talking with a few
> people, we decide to leave out recursion because it seemed likely to
> be the drop that could make the cup spill over. I personally would
> like to see recursion as part of constexpr, but I don't consider a
> recursive factorial a "real world example". If - and only if -
> someone steps forward and argues (in writing and preferably also in
> person at a committee meeting) that recursion is simple in definition
> and implementation terms, that there are important real-world use
> cases, and assures the committee that accepting it will not require
> extra work from already overworked members I'll happily support the
> proposal as - I know - would Gaby.
One could allow an implementation defined limit on recursion depth,
which may be zero.
> I don't see implementation as a key problem. My problem is with the
> (lack of) quality of the examples of need for recursive constexpr.
For motivating examples Sines and Cosines etc in ROM tables based on
e.g frame rate, Newton Raphson approximations , etc etc.
Andy Little
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Mon, 17 Dec 2007 08:13:19 GMT Raw View
Joe Gottman wrote:
> Walter Bright wrote:
>> James Kanze wrote:
>>> I'm not arguing against making more things available as compile
>>> time constants. I'm just saying that the programmer should be
>>> able to express his intent, to avoid thing accidentally getting
>>> used as compile time constants when he doesn't want to guarantee
>>> that as part of the contract.
>>
>> I understand your point, but since a compile time error is issued if
>> anything goes wrong, I don't see a big issue.
>>
>
> Suppose I'm writing some code, and a variable just happens to be a
> compile-time constant without my planning this. Another programmer uses
> the compile-time constant in his code. I never see his code so I don't
> know that this is an issue. If I later modify my code so that the
> variable isn't a compile-time constant then I end up accidentally
> breaking the other programmer's code.
I do understand James' point, which I believe is the same as yours, but
I just don't think it merits a new keyword.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Mon, 17 Dec 2007 17:59:44 GMT Raw View
On Mon, 17 Dec 2007, Walter Bright wrote:
| Joe Gottman wrote:
| > Walter Bright wrote:
| > > James Kanze wrote:
| > > > I'm not arguing against making more things available as compile
| > > > time constants. I'm just saying that the programmer should be
| > > > able to express his intent, to avoid thing accidentally getting
| > > > used as compile time constants when he doesn't want to guarantee
| > > > that as part of the contract.
| > >
| > > I understand your point, but since a compile time error is issued if
| > > anything goes wrong, I don't see a big issue.
| > >
| >
| > Suppose I'm writing some code, and a variable just happens to be a
| > compile-time constant without my planning this. Another programmer uses the
| > compile-time constant in his code. I never see his code so I don't know
| > that this is an issue. If I later modify my code so that the variable isn't
| > a compile-time constant then I end up accidentally breaking the other
| > programmer's code.
|
| I do understand James' point, which I believe is the same as yours, but I just
| don't think it merits a new keyword.
The original generalized constant expression proposal did not
introduce a new keyword. However, feedback (expressed either through
emails or in face to face presentations and discussions) overwhelmingly
asked for a new keyword to precisely help both users and implementers.
And it actually did enhance the semantics.
Users want to check up front when their functions are assured to be
constexpr, instead of blowing later in third party programs or libraries.
Implementers want to know up front when they have to treat a given
function specially -- remember that function calls in general are NOT
constant expressions so many implementations take short circuits while
*parsing*.
There are other subtile points where a keyword helps ensure the proper
semantics -- discussed in detail in the constexpr proposal.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Mon, 17 Dec 2007 17:59:59 GMT Raw View
Joe Gottman wrote:
> Walter Bright wrote:
>> James Kanze wrote:
>>> I'm not arguing against making more things available as compile
>>> time constants. I'm just saying that the programmer should be
>>> able to express his intent, to avoid thing accidentally getting
>>> used as compile time constants when he doesn't want to guarantee
>>> that as part of the contract.
>>
>> I understand your point, but since a compile time error is issued if
>> anything goes wrong, I don't see a big issue.
>>
>
> Suppose I'm writing some code, and a variable just happens to be a
> compile-time constant without my planning this. Another programmer uses
> the compile-time constant in his code. I never see his code so I don't
> know that this is an issue. If I later modify my code so that the
> variable isn't a compile-time constant then I end up accidentally
> breaking the other programmer's code.
This is happening today in C++ and I'm not seeing a problem with that:
statically-initialized and dynamically-initialized static constant data
have the same static type.
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Mon, 17 Dec 2007 20:21:43 GMT Raw View
Gabriel Dos Reis wrote:
> The original generalized constant expression proposal did not
> introduce a new keyword. However, feedback (expressed either through
> emails or in face to face presentations and discussions) overwhelmingly
> asked for a new keyword to precisely help both users and implementers.
> And it actually did enhance the semantics.
>
> Users want to check up front when their functions are assured to be
> constexpr, instead of blowing later in third party programs or libraries.
>
> Implementers want to know up front when they have to treat a given
> function specially -- remember that function calls in general are NOT
> constant expressions so many implementations take short circuits while
> *parsing*.
>
>
> There are other subtile points where a keyword helps ensure the proper
> semantics -- discussed in detail in the constexpr proposal.
Ok, I think I see the problem now. Given:
static int x = foo();
the C++ compiler has no clue whether foo() should be evaluated at
compile time or run time. In the general case, it is not possible for
the compiler to determine if foo() should be done at compile time or not
(recursion depth, execution time is not statically predictable).
The D programming language solves the problem from the opposite
direction than C++ does. It is always determinable, from the context,
whether foo() should be evaluated at compile time or run time. For example,
static int x = foo();
is always evaluated at compile time, since dynamic initializers for
static variables are not allowed (such belong in the static
constructor). This implies, of course, that:
static const int x = foo();
is unambiguously ROMable.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: oma_remove@this_pvv.org (Olve Maudal)
Date: Thu, 6 Dec 2007 21:32:42 GMT Raw View
Two weeks ago, Lars Gullik Bj nnes and I gave a quick
and dirty introduction to C++0x to a group of people at
my company. We had no intention of making a complete and
accurate description, but rather present some of the
stuff that we find interesting. Here is a link to our
slides:
http://www.pvv.org/~oma/cpp0x_aquadi_nov_2007.pdf
I post it here because somebody might find it useful.
- olve
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "maninalift@googlemail.com" <maninalift@googlemail.com>
Date: Thu, 6 Dec 2007 17:27:33 CST Raw View
static assert is nice but not as powerful as the static if in the D
programming language. Example:
template factorial(int n)
{
static if (n == 1)
const factorial = 1;
else
const factorial = n * factorial!(n-1);
}
I do hope this will be as simple and transparent in C++0x.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Fri, 7 Dec 2007 09:39:51 CST Raw View
On Dec 7, 12:27 am, "maninal...@googlemail.com"
<maninal...@googlemail.com> wrote:
> static assert is nice but not as powerful as the static if in the D
> programming language. Example:
>
> template factorial(int n)
> {
> static if (n == 1)
> const factorial = 1;
> else
> const factorial = n * factorial!(n-1);
>
> }
>
> I do hope this will be as simple and transparent in C++0x.
No flame intended, but *this* combination of keywords "template",
"!",
"const", and "static" seems quite unnatural for me.
There exists a proposed feature of C++0x, which comes quite
near to this and that *would* be constexpr. The new constant
expressions
support *could* handle this case, provided it would support recursive
functions. This is outlined in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
On page we find the following paragraph:
"We (still) prohibit recursion in all its form in constant
expressions.
That is not strictly necessary because an implementation limit on
recursion depth in constant expression evaluation would save us
from the possibility of the compiler recursing forever. However,
until
we see a convincing use case for recursion, we don't propose to
allow it."
Assuming, recursion would be supported, this would be written as
follows:
constexpr int factorial(int n)
{
if (n == 1)
return 1;
else
return n * factorial(n-1);
}
This would seem even more readable as the syntax of D ;-)
But your complaints are correct: Since templates already
provide basic recursion support, it would seem natural to
add this capability to constexpr functions, too.
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "maninalift@googlemail.com" <maninalift@googlemail.com>
Date: Fri, 7 Dec 2007 11:55:43 CST Raw View
> Assuming, recursion would be supported, this would be written as
> follows:
>
> constexpr int factorial(int n)
> {
> if (n == 1)
> return 1;
> else
> return n * factorial(n-1);
>
> }
>
> This would seem even more readable as the syntax of D ;-)
I agree with that.
constexpr seems like it would solve many of the problems more
elegantly but there are certainly cases where it wouldn't do the job.
I have never programmed in D but the as far as I understand it "static
if" allows the you to include or exclude bits of code at will as if
you were using #if and #endif but using compile-time information. Note
that the the keyword "is" allows you to bring type information to the
table too. This is one of those things one finds oneself trying to do
but having to use include_if, inelegant inheritance structures and
other things you would rather not show your parents.
I don't want to get "feature happy" but the "static if" seems to me as
one with no knowledge in the area at all rather an easy feature to add
to a compiler, relatively speaking. That is to say it doesn't mess
with anything else, it just adds a layer of logic on top. The compiler
works out which part of the code it needs to compile then tries to do
so. There are other related features in D which might seems sensible
in place but would work less naturally in c++.
The net result is to remove the need for 90% if not all precompiler
stuff, which can't really do the job anyway because it doesn't have
the (compile time) information and the template tricks that are there
to bypass the fact that at compile time you don't officially have the
power to pick which bits of the code you want to compile.
It seems like a win-win feature in a world full of tradeoffs but it is
probably not that simple. Please let me know why I'm wrong (or, less
likely, right).
on conditional compilation:
http://www.digitalmars.com/d/version.html
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: j_richter@gmx.de
Date: Fri, 7 Dec 2007 12:00:25 CST Raw View
On 7 Dez., 16:39, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> Assuming, recursion would be supported, this would be written as
> follows:
>
> constexpr int factorial(int n)
> {
> if (n == 1)
> return 1;
> else
> return n * factorial(n-1);
>
> }
But you still can't write it this way, because multiple returns and
ifs are not supported.
J rg
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Fri, 7 Dec 2007 12:42:56 CST Raw View
On 7 Dez., 19:00, j_rich...@gmx.de wrote:
> But you still can't write it this way, because multiple returns and
> ifs are not supported.
If recursive functions would be supported - as I wrote -
multiple returns *must* be supported, otherwise you
could not stop such beast.
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Fri, 7 Dec 2007 14:19:03 CST Raw View
On 7 Dez., 19:42, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> On 7 Dez., 19:00, j_rich...@gmx.de wrote:
>
> > But you still can't write it this way, because multiple returns and
> > ifs are not supported.
>
> If recursive functions would be supported - as I wrote -
> multiple returns *must* be supported, otherwise you
> could not stop such beast.
OK, I misunderstood your concern. The proper
constexpr approach would be similar to this:
constexpr int factorial(int n)
{
return (n == 1) ? 1: n * factorial(n-1);
}
Sorry for that and Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: yanlinlin <yanlinlin82@gmail.com>
Date: Mon, 10 Dec 2007 01:38:56 CST Raw View
> static assert is nice but not as powerful as the static if in the D
> programming language. Example:
>
> template factorial(int n)
> {
> static if (n == 1)
> const factorial = 1;
> else
> const factorial = n * factorial!(n-1);
>
> }
>
> I do hope this will be as simple and transparent in C++0x.
Can C++0x do like this ?
constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n
- 1); }
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Mon, 10 Dec 2007 14:52:55 GMT Raw View
Daniel Kr=FCgler wrote:
> On 7 Dez., 19:42, "Daniel Kr=FCgler" <daniel.krueg...@googlemail.com>
> wrote:
>> On 7 Dez., 19:00, j_rich...@gmx.de wrote:
>>
>>> But you still can't write it this way, because multiple returns and
>>> ifs are not supported.
>> If recursive functions would be supported - as I wrote -
>> multiple returns *must* be supported, otherwise you
>> could not stop such beast.
>=20
> OK, I misunderstood your concern. The proper
> constexpr approach would be similar to this:
>=20
> constexpr int factorial(int n)
> {
> return (n =3D=3D 1) ? 1: n * factorial(n-1);
> }
>=20
> Sorry for that and Greetings from Bremen,
To clarify something, a possible D compile-time factorial is:
uint factorial(uint n)
{
uint result =3D 1;
foreach (i; 2 .. n) result *=3D i;
return result;
}
Notice that the function uses mutable local state and iteration (a=20
straight C-like loop would also do). This same function can be used for=20
compile-time and run-time evaluation, depending on the invocation context=
:
auto x =3D factorial(5); // run-time call
static y =3D factorial(5); // compile-time call
It's quite hard to do any better than that.
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "maninalift@googlemail.com" <maninalift@googlemail.com>
Date: Mon, 10 Dec 2007 11:43:51 CST Raw View
All the discussion so far has focused on the specific case which can
be solved (and more elegantly) with constexpr, any thoughts on the
more general use "static if" (see my second post). I can certainly see
that it would be useful in some cases, providing a much more elegant
solution, but what I don't know is whether there is a good fundamental
reason why it wouldn't fit with C++, why it would cause headaches or
encourage bad programming.
I am half tempted to try to implement it myself, though I am probably
underestimating the difficulty. Is the code for the experimental C++0x
compiler available? I'll have a look.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Tue, 11 Dec 2007 00:43:55 GMT Raw View
yanlinlin wrote:
> Can C++0x do like this ?
>
> constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n
> - 1); }
>
No, recursion is specifically forbidden with constexpr.
Joe Gottman
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Tue, 11 Dec 2007 03:37:10 GMT Raw View
This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.
--8323584-671441479-1197335042=:3894
Content-Type: TEXT/PLAIN; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Fri, 7 Dec 2007, j_richter@gmx.de wrote:
| On 7 Dez., 16:39, "Daniel Kr=C3=BCgler" <daniel.krueg...@googlemail.com=
>
| wrote:
|=20
| > Assuming, recursion would be supported, this would be written as
| > follows:
| >
| > constexpr int factorial(int n)
| > {
| > if (n =3D=3D 1)
| > return 1;
| > else
| > return n * factorial(n-1);
| >
| > }
|=20
| But you still can't write it this way, because multiple returns and
| ifs are not supported.
If recursion were allowed, I suspect you could write
constexpr int factorial(int n)
{
return n =3D=3D 1? 1 : n * factorial(n-1);
}
--=20
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
--8323584-671441479-1197335042=:3894--
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: nmusatti <nmusatti@gmail.com>
Date: Tue, 11 Dec 2007 09:57:49 CST Raw View
On Dec 7, 12:27 am, "maninal...@googlemail.com"
<maninal...@googlemail.com> wrote:
> static assert is nice but not as powerful as the static if in the D
> programming language. Example:
>
> template factorial(int n)
> {
> static if (n == 1)
> const factorial = 1;
> else
> const factorial = n * factorial!(n-1);
>
> }
>
> I do hope this will be as simple and transparent in C++0x.
Given code like the following:
template <int n>
inline int factorial() {
if ( n == 1 )
return 1;
else
return n * factorial<n-1>();
}
Today's compilers may reasonably be expected to optimize away the test
entirely, and probably even the whole recursive call. Personally I
prefer that compiler writers spend time implementing similar
optimizations rather than your static if.
Cheers,
Nicola Musatti
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Tue, 11 Dec 2007 17:52:53 GMT Raw View
On Mon, 10 Dec 2007, maninalift@googlemail.com wrote:
| All the discussion so far has focused on the specific case which can
| be solved (and more elegantly) with constexpr, any thoughts on the
| more general use "static if" (see my second post).
It helps discussing `real world' problems that a functionality would
solve. XYZ (or factorial) examples tend to be too vague.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Tue, 11 Dec 2007 18:06:11 GMT Raw View
Joe Gottman wrote:
> yanlinlin wrote:
>
>> Can C++0x do like this ?
>>
>> constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n
>> - 1); }
>>
>
> No, recursion is specifically forbidden with constexpr.
It would be great if recursion (and ideally local transient mutable
state) would be allowed in constexpr functions. As things stand now,
constexpr functions are not functional nor imperative and (somewhat
therefore) not Turing-complete. Although I understand Turing
completeness was not part of the charter of constexpr, I believe that
they are too constrained. They just get tantalizingly close to being
useful. Since the template sublanguage is already Turing complete, it
would have been only natural to make constexpr the same, and possibly
following the same approach (pure functional).
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Tue, 11 Dec 2007 23:52:25 GMT Raw View
Daniel Kr=FCgler wrote:
> Assuming, recursion would be supported, this would be written as
> follows:
>=20
> constexpr int factorial(int n)
> {
> if (n =3D=3D 1)
> return 1;
> else
> return n * factorial(n-1);
> }
>=20
> This would seem even more readable as the syntax of D ;-)
Since the D programming language supports CTFE (Compile Time Function=20
Evaluation), a factorial function that executes at compile time would be=20
written as:
int factorial(int n)
{
if (n =3D=3D 1)
return 1;
else
return n * factorial(n-1);
}
Note that there is no syntactic or semantic difference between a=20
function that executes at runtime and at compile time. While you can use=20
static if and templates to do compile time factorials, using ordinary=20
functions to do so is a lot more sensible.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Wed, 12 Dec 2007 18:20:14 GMT Raw View
Walter Bright wrote:
> Daniel Kr=FCgler wrote:
>> Assuming, recursion would be supported, this would be written as
>> follows:
>=20
> Since the D programming language supports CTFE (Compile Time Function=20
> Evaluation), ...
> Note that there is no syntactic or semantic difference between a=20
> function that executes at runtime and at compile time. While you can us=
e=20
> static if and templates to do compile time factorials, using ordinary=20
> functions to do so is a lot more sensible.
>=20
> ----
> Walter Bright
> http://www.digitalmars.com C, C++, D programming language compilers
I'm with Walter on this. I'm not sure how much compile-time evaluat=
ion
we really need in C++, but if we're going to have it, it's better to do i=
t
with a subset of standard C++ than via the horrors of recursive templates.
The main problem with execution at compile time, though, is arrays.
In a language designed not to know how big an array is, and with the
"array=3Dpointer" convention, handling arrays safely at compile time is
a major problem. Yet if you need extensive compile time computation,
it's probably because you need to build some table.
The embedded systems community could use such a capability, because i=
n
that world, you often put constant tables in ROM. The ability to build a
const array at compile time would be useful, and unless you can do that,
compile time computation probably isn't worth the trouble.
John Nagle
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Thu, 13 Dec 2007 06:00:54 GMT Raw View
On Tue, 11 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
| Joe Gottman wrote:
| > yanlinlin wrote:
| >
| > > Can C++0x do like this ?
| > >
| > > constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n
| > > - 1); }
| > >
| >
| > No, recursion is specifically forbidden with constexpr.
|
| It would be great if recursion (and ideally local transient mutable state)
| would be allowed in constexpr functions. As things stand now, constexpr
| functions are not functional nor imperative and (somewhat therefore) not
| Turing-complete.
`functional' does not imply Turing completeness. The Calculus of
Inductive Construction (for example) is functional, but not Turing complete.
And that isn't necessarily a bad thing.
And I would be reluctant to load the language of C++'s type system
with imperative features. Not that it would not be useful, but I
believe that language is already complex enough.
| Although I understand Turing completeness was not part of the
| charter of constexpr, I believe that they are too constrained. They just get
| tantalizingly close to being useful. Since the template sublanguage is already
| Turing complete, it would have been only natural to make constexpr the same,
| and possibly following the same approach (pure functional).
`Turing completeness' is a nice abstract property. So are `being
functional' or `being imperative'. We had carefully considered all
those properties, along with the actual real world problems we were
trying to solve. The attentive reader of the various versions of the
constexpr proposal would notice that we discussed the problem we were
trying to solve first. I lacked time to conduct a thorough analysis of
real world important use cases that might served by all those nice
properties the current specification does not possess, along with their
specifications and implementation complexity. If you have such a list,
it would be of great help.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Thu, 13 Dec 2007 11:39:38 CST Raw View
On Dec 12, 12:52 am, wal...@digitalmars-nospamm.com (Walter Bright)
wrote:
> Daniel Kr gler wrote:
> > Assuming, recursion would be supported, this would be written as
> > follows:
> > constexpr int factorial(int n)
> > {
> > if (n == 1)
> > return 1;
> > else
> > return n * factorial(n-1);
> > }
> > This would seem even more readable as the syntax of D ;-)
> Since the D programming language supports CTFE (Compile Time
> Function Evaluation), a factorial function that executes at
> compile time would be written as:
> int factorial(int n)
> {
> if (n == 1)
> return 1;
> else
> return n * factorial(n-1);
> }
> Note that there is no syntactic or semantic difference between
> a function that executes at runtime and at compile time. While
> you can use static if and templates to do compile time
> factorials, using ordinary functions to do so is a lot more
> sensible.
You definitly want to separate the intent somehow. If my intent
is that the return value of the function can be used as an
integral constant expression, e.g. as an array dimension, then
you definitly want to say so somewhere. For one thing, it's an
essential part of the contract, and for another, you want the
compiler to complain if it cannot evaluate the function at
compile time. Presumably, D would cease to evaluate the above
at compile time if someone added a print statement to it, say
for debugging reasons. In the case of C++, of course, calling
any function not defined in the current translation unit would
probably suffice to inhibit compile time evaluation.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Thu, 13 Dec 2007 21:50:57 GMT Raw View
Gabriel Dos Reis wrote:
> I lacked time to conduct a thorough analysis of
> real world important use cases that might served by all those nice
> properties the current specification does not possess, along with their
> specifications and implementation complexity. If you have such a list,
> it would be of great help.
Two obvious applications of compile-time computation that come to mind
are (1) generating the correct formatting code from printf-like string
format specifiers and (2) compiling a string regular expression into a
finite automaton. In general, adapting DSLs into C++ require significant
computation best taken care of statically.
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: walter@digitalmars-nospamm.com (Walter Bright)
Date: Thu, 13 Dec 2007 22:00:16 GMT Raw View
James Kanze wrote:
> If my intent
> is that the return value of the function can be used as an
> integral constant expression, e.g. as an array dimension, then
> you definitly want to say so somewhere.
It's not necessary. For example, to use it as an array dimension:
int foo[factorial(3)];
> For one thing, it's an essential part of the contract,
I don't agree. If it cannot be evaluated at compile time, and you use it
in a context where it must be, the compiler will tell you (issue an
error message). Similarly,
int x;
int foo[x + 3];
will produce an error message because x cannot be evaluated at compile
time. A contract isn't necessary.
Although D doesn't (yet) have the semantic notion of a 'pure' function,
functions that are CTFE-capable must currently be a subset of pure
functions.
> In the case of C++, of course, calling
> any function not defined in the current translation unit would
> probably suffice to inhibit compile time evaluation.
Of course, the compiler would need the function body available to it.
But John Nagle has a point in that unless the core language has arrays
in it so that arrays can be manipulated at compile time, CTFE capability
may not be that useful. The D programming language has core strings,
arrays, associative arrays, and tuples, enabling CTFE to shine.
----
Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Fri, 14 Dec 2007 17:43:32 GMT Raw View
On Thu, 13 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
| Gabriel Dos Reis wrote:
| > I lacked time to conduct a thorough analysis of
| > real world important use cases that might served by all those nice
| > properties the current specification does not possess, along with their
| > specifications and implementation complexity. If you have such a list,
| > it would be of great help.
|
| Two obvious applications of compile-time computation that come to mind are (1)
| generating the correct formatting code from printf-like string format
| specifiers and (2) compiling a string regular expression into a finite
| automaton. In general, adapting DSLs into C++ require significant computation
| best taken care of statically.
that is only a third of what I would appreciate to have :-)
A thorough analysis of:
(a) real world important use cases that might be served by all those
nice properties the current specification does not possess;
(b) specification of the `nice' properties in Standardese;
(c) implementation complexity.
I suspect that any solution to your suggested obvious applications
would need some kind of data structures.
Assuming you had recursive constexpr functions, could you share your
solutions to those application problems?
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 14 Dec 2007 17:44:11 GMT Raw View
on Wed Dec 12 2007, nagle-AT-animats.com (John Nagle) wrote:
>> Note that there is no syntactic or semantic difference between a
>> function that executes at runtime and at compile time. While you can
>> use static if and templates to do compile time factorials, using
>> ordinary functions to do so is a lot more sensible.
>>
>> ----
>> Walter Bright
>> http://www.digitalmars.com C, C++, D programming language compilers
>
> I'm with Walter on this. I'm not sure how much compile-time evaluation
> we really need in C++, but if we're going to have it, it's better to do it
> with a subset of standard C++ than via the horrors of recursive
> templates.
I'm with you and Walter.
> The main problem with execution at compile time, though, is arrays.
> In a language designed not to know how big an array is, and with the
> "array=pointer" convention, handling arrays safely at compile time is
> a major problem. Yet if you need extensive compile time computation,
> it's probably because you need to build some table.
It's easy enough to make the compile-time execution fully checked for
such errors. It doesn't have to run fast, dangerous object code to be
millions of times faster than computation with templates is.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: bjarne <bjarne@gmail.com>
Date: Fri, 14 Dec 2007 20:46:29 CST Raw View
On Dec 14, 11:43 am, g...@cs.tamu.edu (Gabriel Dos Reis) wrote:
> On Thu, 13 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
>
> | Gabriel Dos Reis wrote:
> | > I lacked time to conduct a thorough analysis of
> | > real world important use cases that might served by all those nice
> | > properties the current specification does not possess, along with their
> | > specifications and implementation complexity. If you have such a list,
> | > it would be of great help.
> |
> | Two obvious applications of compile-time computation that come to mind are (1)
> | generating the correct formatting code from printf-like string format
> | specifiers and (2) compiling a string regular expression into a finite
> | automaton. In general, adapting DSLs into C++ require significant computation
> | best taken care of statically.
>
> that is only a third of what I would appreciate to have :-)
>
> A thorough analysis of:
> (a) real world important use cases that might be served by all those
> nice properties the current specification does not possess;
>
> (b) specification of the `nice' properties in Standardese;
>
> (c) implementation complexity.
>
> I suspect that any solution to your suggested obvious applications
> would need some kind of data structures.
>
> Assuming you had recursive constexpr functions, could you share your
> solutions to those application problems?
>
Gaby is polite and an optimist :-) I'd like to see something quite
substantial.
Of course, we considered recursion (and other extensions to what is
currently accepted), but our primary aim wasn't to make constepr a
theoretically nice Turing complete compile-time evaluation mechanism.
It was to get a mechanism that could handle a longish list of
relatively simple real-world needs for compile-time evaluation. We
worried about going beyond that out of fear of serious opposition
based on lack of experience in established languages, complexity, "yet
another feature", etc., and pure FUD. Based on talking with a few
people, we decide to leave out recursion because it seemed likely to
be the drop that could make the cup spill over. I personally would
like to see recursion as part of constexpr, but I don't consider a
recursive factorial a "real world example". If - and only if -
someone steps forward and argues (in writing and preferably also in
person at a committee meeting) that recursion is simple in definition
and implementation terms, that there are important real-world use
cases, and assures the committee that accepting it will not require
extra work from already overworked members I'll happily support the
proposal as - I know - would Gaby.
I don't see implementation as a key problem. My problem is with the
(lack of) quality of the examples of need for recursive constexpr.
-- Bjarne Stroustrup; http://www.research.att.com/~bs
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail@erdani.org>
Date: Fri, 14 Dec 2007 22:25:24 CST Raw View
Gabriel Dos Reis wrote:
> On Thu, 13 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
>
> | Gabriel Dos Reis wrote:
> | > I lacked time to conduct a thorough analysis of
> | > real world important use cases that might served by all those nice
> | > properties the current specification does not possess, along with their
> | > specifications and implementation complexity. If you have such a list,
> | > it would be of great help.
> |
> | Two obvious applications of compile-time computation that come to mind are (1)
> | generating the correct formatting code from printf-like string format
> | specifiers and (2) compiling a string regular expression into a finite
> | automaton. In general, adapting DSLs into C++ require significant computation
> | best taken care of statically.
>
> that is only a third of what I would appreciate to have :-)
>
> A thorough analysis of:
> (a) real world important use cases that might be served by all those
> nice properties the current specification does not possess;
>
> (b) specification of the `nice' properties in Standardese;
>
> (c) implementation complexity.
>
> I suspect that any solution to your suggested obvious applications
> would need some kind of data structures.
>
> Assuming you had recursive constexpr functions, could you share your
> solutions to those application problems?
Of course not. It would be a large undertaking, and a futile one at this
point. As far as principles go, having rebindable symbols and recursion
would make constexpr a pure functional language, for which there is
quite a large body of theory and practice.
My point is simple. I do appreciate the concern for ease of
implementation that permeates the constexpr proposal. It's pretty clear
to me and probably everybody on the committee that stretching the
proposal any further would push the envelope too far given the time and
space constraints that the committee is having. But we cannot reframe
that concern into demeaning applications of the more powerful amenities
that were left out. We can't have those grapes. Let's not deem them sour.
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 15 Dec 2007 05:23:43 GMT Raw View
On Fri, 14 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
| Gabriel Dos Reis wrote:
| > On Thu, 13 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
| >
| > | Gabriel Dos Reis wrote:
| > | > I lacked time to conduct a thorough analysis of
| > | > real world important use cases that might served by all those nice
| > | > properties the current specification does not possess, along with their
| > | > specifications and implementation complexity. If you have such a list,
| > | > it would be of great help.
| > |
| > | Two obvious applications of compile-time computation that come to mind are
| > | (1)
| > | generating the correct formatting code from printf-like string format
| > | specifiers and (2) compiling a string regular expression into a finite
| > | automaton. In general, adapting DSLs into C++ require significant
| > | computation
| > | best taken care of statically.
| >
| > that is only a third of what I would appreciate to have :-)
| >
| > A thorough analysis of:
| > (a) real world important use cases that might be served by all those
| > nice properties the current specification does not possess;
| >
| > (b) specification of the `nice' properties in Standardese;
| >
| > (c) implementation complexity.
| >
| > I suspect that any solution to your suggested obvious applications
| > would need some kind of data structures.
| >
| > Assuming you had recursive constexpr functions, could you share your
| > solutions to those application problems?
|
| Of course not. It would be a large undertaking, and a futile one at this
| point. As far as principles go, having rebindable symbols and recursion
| would make constexpr a pure functional language, for which there is
| quite a large body of theory and practice.
constexpr is already pure functional.
But, again, that wasn't the point of the exercise.
| My point is simple. I do appreciate the concern for ease of
| implementation that permeates the constexpr proposal. It's pretty clear
| to me and probably everybody on the committee that stretching the
| proposal any further would push the envelope too far given the time and
| space constraints that the committee is having. But we cannot reframe
| that concern into demeaning applications of the more powerful amenities
| that were left out.
I haven't seen anybody doing that.
--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
http://www.cs.tamu.edu/people/faculty/gdr
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: SeeWebsiteForEmail@erdani.org ("Andrei Alexandrescu (See Website For Email)")
Date: Sat, 15 Dec 2007 06:59:00 GMT Raw View
Gabriel Dos Reis wrote:
> On Thu, 13 Dec 2007, Andrei Alexandrescu (See Website For Email) wrote:
>
> | Gabriel Dos Reis wrote:
> | > I lacked time to conduct a thorough analysis of
> | > real world important use cases that might served by all those nice
> | > properties the current specification does not possess, along with their
> | > specifications and implementation complexity. If you have such a list,
> | > it would be of great help.
> |
> | Two obvious applications of compile-time computation that come to mind are (1)
> | generating the correct formatting code from printf-like string format
> | specifiers and (2) compiling a string regular expression into a finite
> | automaton. In general, adapting DSLs into C++ require significant computation
> | best taken care of statically.
>
> that is only a third of what I would appreciate to have :-)
>
> A thorough analysis of:
> (a) real world important use cases that might be served by all those
> nice properties the current specification does not possess;
>
> (b) specification of the `nice' properties in Standardese;
>
> (c) implementation complexity.
>
> I suspect that any solution to your suggested obvious applications
> would need some kind of data structures.
>
> Assuming you had recursive constexpr functions, could you share your
> solutions to those application problems?
Of course not. It would be a large undertaking, and a futile one at this
point. As far as principles go, having rebindable symbols and recursion
would make constexpr a pure functional language, for which there is
quite a large body of theory and practice.
My point is simple. I do appreciate the concern for ease of
implementation that permeates the constexpr proposal. It's pretty clear
to me and probably everybody on the committee that stretching the
proposal any further would push the envelope too far given the time and
space constraints that the committee is having. But we cannot reframe
that concern into demeaning applications of the more powerful amenities
that were left out. We can't have those grapes. Let's not deem them sour.
Andrei
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@btinternet.com>
Date: Sat, 15 Dec 2007 10:58:49 CST Raw View
Andrei Alexandrescu (See Website For Email) wrote:
> Of course not. It would be a large undertaking, and a futile one at this
> point. As far as principles go, having rebindable symbols and recursion
> would make constexpr a pure functional language, for which there is
> quite a large body of theory and practice.
>
> My point is simple. I do appreciate the concern for ease of
> implementation that permeates the constexpr proposal. It's pretty clear
> to me and probably everybody on the committee that stretching the
> proposal any further would push the envelope too far given the time and
> space constraints that the committee is having. But we cannot reframe
> that concern into demeaning applications of the more powerful amenities
> that were left out. We can't have those grapes. Let's not deem them sour.
>
>
Indeed, but note that such things as recursion could be provided as an
extension and if that proved successful could provide the evidence to
incorporate that into the following release of the C++ Standard. Just
because the Standard is conservative does not prevent implementers being
liberal.
---
[ 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.comeaucomputing.com/csc/faq.html ]