Just Software Solutions

C++0x Final Committee Draft Published - Please Comment

Friday, 02 April 2010

Earlier this week, the Final Committee Draft (FCD) of the C++0x standard was published. This means that C++0x is now in the final stages of bug fixing and wordsmithing before publication. If all goes to plan, the draft will move to Final Draft International Standard (FDIS) early in 2011, and will be a new standard by the end of 2011.

The publication of the FCD means that the draft standard has now been officially put up for review by the national standards bodies of ISO's member countries. The British Standards Institution is one of several national bodies that is actively involved in the standardisation of the C++ language. The panel members of the C++ Committee of the BSI, IST 5/-/21, are currently compiling a list of comments on the FCD. We intend to submit these as the BSI's National Body comments, aimed at getting issues with the FCD addressed before it becomes the new international standard for C++.

We're welcoming additional comments, and would like to provide a channel for anyone who may be interested in the C++0x Standard, but not able to be fully involved in the standards process, to submit comments. Note that not all comments — regardless of whether they are submitted by panel members or non-members — will go forward.

Here is some guidance on what we are looking for:

  • Suggestions for how to improve the clarity of the wording, even if that's just by adding a cross-reference to a relevant paragraph elsewhere;
  • Comments that identify any under/over specification; and
  • Comments highlighting inconsistencies or contradictions in the draft text.

Comments should be specific and preferably should include suggested updated wording (and if you need help formulating updated wording we can provide it, within reason) — the C++ standards committee is working to a very tight schedule in order to get C++0x out as soon as possible, and comments without wording (which therefore require more work from the committee) are more likely to be rejected.

The time for adding/removing features has now passed, so comments should focus on improving the draft as it stands rather than suggesting new features.

Owing to the time scale for submission to BSI and ISO, comments need to be submitted by Friday 18th June 2010.

If you have any comments, feel free to post them in the comment section of this blog entry, or email them to me. I will forward all appropriate suggestions to the rest of the BSI panel (whether or not I agree with them).

Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: , , ,
Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.

53 Comments

by zerothat at 15:00:33 on Monday, 21 January 2019

Greetings,

I'm almost afraid to mention it but I was looking at n3092 at ios::failure and noticed a lot of throw() specifications. Will these turn into noexcept?

Are throw() and noexcept and noexcept(true) in fact equivalent? If so then it becomes a matter of syntactic sugar. Although if we're trying to deprecate exception specifications it might be nice to go with noexcept.

Ed
by Ed Smith-Rowland at 15:00:33 on Monday, 21 January 2019

"Consume operation" appears in multiple places in N3092, but it is never defined. 1.10/7 "defines" "acquire operation" and "release operation" relative to one another, but only in the context of weakly defining "synchronize with." Similarly, "acquire fence" and "release fence" are ill defined. Shouldn't those terms be better defined to prevent ambiguity of interpretation?

by Rob Stewart at 15:00:33 on Monday, 21 January 2019

5.7/3 appears to be the entire definition of addition and subtraction, yet there is no mention of the type of the result. If two unsigned values are subtracted, is the result signed or unsigned? If signed, what if the signed type corresponding to the unsigned type is too small? Is the next larger signed type selected? According to an old C book I have (C: A Reference Manual, 2nd ed, Harbison and Steele), "the result of subtracting one unsigned integer from another is always unsigned and therefore cannot be negative." It may be that this behavior is specified by C and incorporated by C++ from the C standard, but I don't have access to the C standard to know.

by Rob Stewart at 15:00:33 on Monday, 21 January 2019

I have three comments:

1. There is sometimes extraneous punctiation inside quotations, for instance clause 3.9.2 reads 'A pointer to objects of type T is referred to as a “pointer to T.”'. This makes the standard harder to understand.

2. Paper N3039 (Constexpr functions with const reference parameters) gives the constructor of std::pair and the functions min and max as examples of functions that would benefit from this extension but constexpr has not been added to their function signatures.

3. Library issue 550 has not been clearly justified as being a defect that deserves stopping the compiler from converting expressions such as pow(x,2) to x*x at compile-time. The example used to introduce it is contrived and the functionality suggested is possible with a cast.

by Andrew Hain at 15:00:33 on Monday, 21 January 2019

@Dmitry: I have added your final comment about atomic_signal_fence to the BSI list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Michael: Thanks for your comment. I believe that override is best suited as an attribute, since it fits the description for a perfect attribute: if the code with the attribute compiles correctly with the attribute applied, then it will also compile correctly with the same semantics if the attribute is removed or ignored.

Regardless, I have added it to the BSI discussion list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Douglas Thanks for your comment. I have added it to the BSI discussion list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Rob: 1.10/3 deliberately doesn't place any temporal constraints on the definition of conflict. Operations conflict if they refer to the same object. If they don't have any ordering constraints and they are not both atomic accesses then there is a data race. If they are both atomic accesses, or there are ordering constraints such that one happens-before the other then everything is OK.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@zerothat: No, variable-sized arrays are not part of C++0x. I can't see how you could sensibly use them as class members anyway, since that would mean the class size varied at runtime. Under such circumstances a std::vector would be more appropriate. You can define a template which specifies the size of the member array, but each instantiation would be a distinct type, and would need to be specified at compile time.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@zerothat: You can specify a distinct allocator per instance --- just pass in an allocator to the constructor of your Standard Library object (e.g. std::vector). The type of the allocator must be specified as a template parameter at compile time though.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Ed: Some of the throw() clauses in the library may well become noexcept, but not necessarily all of them. I've added it to the BSI list

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Rob: A consume operation is an atomic load (or RMW) operation tagged with memory_order_consume --- see 29.3p1. Similarly for acquire and release operations. The semantics of fences is defined in 29.8 --- in 29.8p1, an acquire fence is defined as a fence with acquire semantics (implying the use of memory_order_acquire, memory_order_acq_rel or memory_order_seq_cst).

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Rob: The type of a binary operation on objects of arithmetic types is defined in 5p10 as the same type as the operands after the operands have been converted to a common type. The result of subtracting one unsigned value from another is thus unsigned.

3.9p4 says "Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2^n where n is the number of bits in the value representation of that particular size of integer."

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Andrew: 1) The full stop inside the quotation marks in 3.9.2 is correct punctuation, as this is the end of the sentence.

2) I've added this to the BSI discussion list

3) The compiler can convert pow(x,2) to x*x if x is of type double or long double. If it is of type float then it must be done as (double)x*(double)x, but it is still allowed to expand the constant integer to a series of multiplications.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Anthony: Many thanks for considering and passing it on. IMHO, apart from thinking that the attribute version looks messy, my biggest concern is that individual developers can omit the attribute if it is not enforced by e.g. an compiler option. In my opinion and experience there are less problems with false overrides or problems when refactoring overrides with an mandatory override attribute or keyword as e.g. in C#. I believe that in the long run annotating overrides will become mandatory and therefore I think it should become a keyword rather then a attribute. But falling that I would like to see a compiler option to enforce correct annotation.

by Michael at 15:00:33 on Monday, 21 January 2019

This is so good that we are going to know about the super mario run game and how to unlock all level in the game.

by cheat super mario run at 15:00:33 on Monday, 21 January 2019

I'm way past the deadline, I know, but maybe you can still put this one the Agenda for the August meeting: throughout section 1.10, "scalar object or bit field" should probably be replaced by "memory location", as defined in 1.7?

by Marc Mutz at 15:00:33 on Monday, 21 January 2019
What an inspiring article you wrote! I totally like the useful info shared in the article.
by R4DS at 15:00:33 on Monday, 21 January 2019

Section 6.5 note 5 says that loops with no relevant side-effect can be assumed to terminate ("intended to allow compiler transformations, such as removal of empty loops, even when termination cannot be proven").

What's not clear, is whether eliminating the loop is allowable when non-termination is easily proven. For example, an infinite loop such as for(;;){}. Eliminating such explicit infinite loops will break much existing code that does not expect execution to proceed past the loop in such cases.

(Yes it's way past the deadline; where does one provide comments for clarifications in the next revision?)

by Marc G at 15:00:33 on Monday, 21 January 2019
Just for completeness: Mutexes are still called locks in 1.10. Have to be called mutexes to be consistent with 30.4. And locks are just helper classes.
by Dmitry V'jukov at 15:00:33 on Monday, 21 January 2019

Why there are no optional atomic_[u]intN_t typedefs (only atomic_[u]int_fast/leastN_t)? I would strongly expect them to be defined provided that according [u]intN_t typedefs are defined. IMO simple [u]intN_t are MUCH more widely used than fast/least analogs.

by Dmitry V'jukov at 15:00:33 on Monday, 21 January 2019
I would expect it to be explicitly stated that atomic_thread_fence() IS-A atomic_signal_fence(). IMVHO it's reasonable, and may be useful in some situations.
by Dmitry V'jukov at 15:00:33 on Monday, 21 January 2019

Thanks for your comments Dmitry. I have added the comments on mutexes vs locks in 1.10 and atomic_intN_t typedefs to the BSI list.

I think that the FCD is clear that atomic_thread_fence IS-A atomic_signal_fence --- atomic_signal_fence is defined to be the same as atomic_thread_fence but restricted to a signal handler on the same thread (29.8p6). If you don't think this is clear enough, and can propose better wording then I'll add it to the list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

Core Issue 968 / N3034 (Disambiguating [[ )

I am not happy with the proposed solution for this Issue ( to use the max-munch principle for the sequence [ [ ) as it leads to a very simmilar problem that C++0x just got rid of with >> in templates, i.e. the examples from N3034:

int p[10]; void f() { int x = 42; int(p[[x]{return x;}()]); // Error: malformed attribute on a nested // declarator-id and not a function-style cast of // an element of p. new int[[]{return x;}()]; // Error even though attributes are not allowed

} // in this context.

would become legal (and useful) code with introduced braces(!):

int(p[([x]{return x;}())]); new int[([]{return x;}())];

That introduce the same "minor, but persisting, annoying, and somewhat embarrassing problem" (quote from Daveed Vandevoorde on >>, who is also author of N3034) that n1757 solves for right angle brackets. Even worse, introducing spaces:

int(p[ [x]{return x;}()]); new int[ []{return x;}()];

will also not work, which I find doubly surprising (even though I understand the reasons and mechanics of why it is so).

Since it seems that implementing the proper (IMVHO) behavior is not to onerous (see the comments from Sean Hunt in this comp.std.c++ thread http://groups.google.de/group/comp.std.c++/browse_frm/thread/359da24f9d9067a9) and one of C++0x's goals is to reduce surprises I think that all forms presented here should work.

by Fabio Fracassi at 15:00:33 on Monday, 21 January 2019

Hi Fabio,

I've added this comment to the list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

The handling of initialization to references to arrays needs to be clearly handled by the algorithms for initialization (8.5).

It is not clear what happens in these cases:

const int (&arr)[2] = { 1, 2 }; const int (&arr)[2] = { 1 }; const int (&arr)[2] = {};

int (&&arr)[2] = { 1, 2 }; int (&&arr)[2] = { 1 }; int (&&arr)[2] = {};

Thanks!

by Faisal Vali at 15:00:33 on Monday, 21 January 2019

Re: I think that the FCD is clear that atomic_thread_fence IS-A atomic_signal_fence --- atomic_signal_fence is defined to be the same as atomic_thread_fence but restricted to a signal handler on the same thread (29.8p6).

Initially I interpret the wording as if signal fence has different semantics than thread fence rather than restricted semantics of thread fence. But it seems that you are right. One more note of signal fences: 29.8p6 "... except that synchronizes with relationships are established only between a thread and a signal handler executed in the same thread". The problem is that thread fence not only establish synchronizes with relationships, there are semantics of fences that are expressed not in terms of synchronizes with relationships (for example see 29.3p5). So I would expect something along the lines of "... except that EVERYTHING is restricted to a thread and a signal handler executed in the same thread".
by Dmitry V'jukov at 15:00:33 on Monday, 21 January 2019

Section 20.9.10.5: "Each object of a type U instantiated form the unique_ptr template..." I think "form" was supposed to be "from".

by Scott French at 15:00:33 on Monday, 21 January 2019

On page 75: an assignment expressions should be: an assignment expression

by Krisztian Paczari at 15:00:33 on Monday, 21 January 2019

[expr.prim.lambda] 5.1.2/16 has text which begins "If a lambda-expression m1 captures an entity and that entity is captured by an immediately enclosing lambda expression m2..." - that is, it describes a situation with m2 enclosing m1, and then describes the capture transformation in these terms.

The example given to support this, however, turns this all around and shows m1 enclosing m2. This doesn't make either the text or the example incorrect in any sense, but I would suggest that it adds a level of confusion that is easily avoided.

Suggested wording: All references to m1 from the beginning of 5.1.2/16 up to the last occurrence before '[Example ' to be replaced by m2, and vice versa.

Rationale for suggested wording: all other examples that use the 'mN' notation for lambda expressions and which involve nesting apply increasing N (by 1, from 1) to indicate increasing nesting depth.

by Paul Bibbings at 15:00:33 on Monday, 21 January 2019

[expr.prim.lambda] 5.1.2/12. In the example code given the local struct s1 has a member function with signature int s1::work(int n) whose definition does not include an appropriate return statement; neither does it include the conventional "// ..." to indicate that the example is intended to be incomplete.

Suggested change: change the signature of this member function to void s1::work(int n), as the return of int does not contribute to the example.

by Paul Bibbings at 15:00:33 on Monday, 21 January 2019

[lex.icon] 2.14.2/2 Table 5 - 'Types of integer constants' In the penultimate row for this table (for suffix `ll or LL') it gives the `Octal or hexadecimal constant' in the third column as one of: long long int unsigned long int Unless I am misunderstanding something fundamental, this second should be: unsigned long long int

by Paul Bibbings at 15:00:33 on Monday, 21 January 2019

In Annex A [gram], paragraph 1, I think the hyperlinks to disambiguation rules should include section 8.2 (possibly in place of 7.1?)

by Ben Voigt at 15:00:33 on Monday, 21 January 2019
by Ross Levine at 15:00:33 on Monday, 21 January 2019

@Faisal

I think that the current wording is quite clear on references to arrays. References of any kind must be initialized from an object or other reference of an appropriate kind. A brace initializer list is not an object, and cannot be bound to any reference, so all your examples are errors.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Scott: Thanks.

@Krisztian: Can you give a clause reference number such as 1.2.3 paragraph 6? I cannot find the text to which you refer.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

6.5.4/1 requires that range-based for loops behave as if they had "{ auto&& __range = (expression); for (auto __begin = begin_expr, __end = end_expr; ..." which implies that __begin and __end must have the same type. However, this prevents stateful iterators with an end sentinel of a different type. Since range-based for loops' equivalent code already introduces a block (for the __range variable), could __begin and __end be placed there, as "auto __begin = begin_expr; auto __end = end_expr;"?

Example of what this change would allow, only the relevant details shown with ctors, op*, op++, etc. omitted: (apologies if the formatting is lost)

struct End {}; struct Counter { Counter& begin() { return *this; } // used by begin_expr End end() { return End(); } // used by end_expr bool operator!=(End) const { return _current != _end; }

Counter(int begin, int end) : _current(begin), _end(end) {} int _current, _end; };

void use_example() { for (auto n : Counter(0, 10)) { // n takes values from 0..9 } }

by Roger Pate at 15:00:33 on Monday, 21 January 2019

@Paul

Thanks for your comments. I've added them to the BSI list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

If i'm not missing something, 14.6.2.1/3 says that in the definition of a class template or member of a class template, the injected-class-name refers to the current instantiation. The template name followed by the argument list enclosed in "<..>" also refers to the current instantiation, but only in the definition of a primary class template. That results in an odd situation:

template<typename T> struct A { typedef int type; void f(type); }; // here we are outside the definition of "A"

template<typename T> void A::f(A::type) { } // OK: "A" is the injected-class-name

template<typename T> void A::f(A<T>::type) { } // ill-formed: "A<T>" is not the injected-class-name. Needs "typename "!

If you would define the member-function within the primary class template, bullet 2 would apply:

template<typename T> struct A { typedef int type; void f(A<T>::type) { } // OK: name of A followed by arguments enclosed in <..> };

I think that this state of affairs isn't any good.

-> Suggested solution: Change 14.6.2.1/1 bullet2 to apply also to members of the primary class template. The same for bullet4 talking about partial specializations. Since partial specializations are also class templates, i wonder whether one could also smelt together bullet2 and bullet4 and only talk about "class template".

I would also like to change the introductory text of 14.6.2.1/1 to

"In the definition of a class template, a member of a class template, or a member of a member of a class template".

Since a nested class is already a member.

by Johannes Schaub at 15:00:33 on Monday, 21 January 2019

C++0x does not allow this code

template<typename T> struct id { typedef T type; }; template<typename T> void f() { int id<T>::type::*p = 0; } struct A { };

int main() { f<A>(); }

The reason is that it requires "typename" before "id<T>::type", but "typename" is not allowed at that place by the syntax. Ultimately, current compilers accept this.

-> Suggested solution: Change 14.6/5 to

A quali&#64257;ed name used as the name in a mem-initializer-id, a base-speci&#64257;er, an elaborated-type-speci&#64257;er or the nested-name-specifier of a pointer-to-member declarator is implicitly assumed to name a type, without the use of the typename keyword.

by Johannes Schaub at 15:00:33 on Monday, 21 January 2019

Hi Anthony,

Most threading APIs provide a way to create "dynamic" thread local objects (TlsAlloc/TlsFree). They are useful when one wants to attach thread local object to an object (rather than to a class with "static thread_local" declaration). For example consider:

class scheduler { ... struct thread_local_part {...}; thread_local thread_local_part thread_; // no 'static' here ... };

And a user must be able to create several independent instances of scheduler. C1x provides a way to create thread local objects dynamically. I would expect to have something similar in C++0x.
by Dmitry V'jukov at 15:00:33 on Monday, 21 January 2019

I just ran into a vexing problem with overload resolution. I don't know if this suggestion counts as a "feature" or not but it certainly is in the spirit of making the language more amenable to good software engineering.

I found a problem using boost::shared_ptr the other day and posted about it here:

http://lists.boost.org/boost-users/2010/05/59260.php

The first problem reported in the thread is the significant one. The other issue only came up when trying to hack around the first one so I don't consider it important.

The bottom line is that overload resolution as currently worded in the standard can cause template instantiations which are illegal. My expectation as a language user was that such instantiations wouldn't be an issue if there was a clear Exact match on all function arguments. In that case I expected the compiler to essentially short-circuit overload resolution and treat ill-formed instantiations in a manner similar to SFINAE.

There does not appear to be any requirement in the standard to do such short-circuiting. I'm not a language lawyer so I don't know what language to require this would look like in the standard and would appreciate help with writing it.

As is, it appears that gcc does some form of short-circuiting, but any code relying on it is non-portable. At the very least, perhaps the standard should clarify whether all instantiations involved in calls to candidate functions must be done during overload resolution and specify what should happen in the case of an invalid instantiation.

I would much prefer that the standard require short-circuited overload resolution as it allows greater flexibility in decoupling code as explained in the linked thread.
by David Greene at 15:00:33 on Monday, 21 January 2019
Your blog is extremely good,excellent operate.More than likely a lot of will certainly believe.it is very interesting thanks for sharing.
by Amiclubwear coupons at 15:00:33 on Monday, 21 January 2019

@Ross Levine,

noexcept has been deliberately specified as unchecked. If you add checking then this either requires that the compiler identify every possible route through your code (which requires solving the halting problem) in order to verify whether or not your code can throw, or you force a try/catch block around the use of code that is not annotated as noexcept or throw() within a noexcept function, *even if you know it cannot throw*.

e.g.

int square_root(int i)

{

if(i<0) throw "out of range";

return sqrt(i);

}

int pinned_square_root(int i) noexcept

{

if(i<0) return 0;

return square_root(i); // i never less than zero, so this doesn't throw

}

This is allowed by the current draft, but a checked noexcept would require a try/catch around the call to square_root in pinned_square_root, which would eliminate much of the optimization potential gained from using noexcept.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Ben: Thanks for the comment. I've added it to the list.

@Johannes: Thanks for the comments. I've added them to the list.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Dmitriy: I understand the desire for dynamic thread-local variables. I believe that boost::thread_specific_ptr is used for that quite extensively. However, there are considerable issues surrounding such usage, not least of which is what happens to values associated with other threads when the object is destroyed on one thread (e.g. the class object of which it is a member is destroyed). This is a non-trivial change, and at the very least will require a full paper specifying the semantics. If you write such a paper I will add it to the list for discussion at BSI prior to submission of the BSI comments.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@Roger: I've forwarded your comment. However, the use of distinct types for begin and end would be novel --- all existing ranges in the C++ standard have the begin and end being the same type, and all the algorithms that operate on ranges require this.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019

@David: I've forwarded your comment to the rest of BSI.

by Anthony Williams at 15:00:33 on Monday, 21 January 2019
I would like to see override in a native non kludge (aka attribute) manner (like C#). The benefits would clearly justify braking a few million lines of code and fixing them would only would that a fraction of the time wasted this finding override related bugs.
by Michael at 15:00:33 on Monday, 21 January 2019

Hi Anthony,

Firstly, thank you for accepting comments.

It seems that lvalues of any sort don't bind to non-const rvalue ref args, even if an intermediate temporary would be created. See the discussion at http://stackoverflow.com/questions/2748866/c0x-rvalue-references-and-temporaries. I'll summarise that here:

Assume that std::vector has push_back overloads declared as follows, with SFINAE omitted for clarity: void push_back(const T &); //Copies the const T & into the vector's storage void push_back(T &&); //Moves the T && into the vector's storage

Then this code appears to behave as commented, as of N3090: const char * cchar = "Hello, world"; std::vector<std::string> v; v.push_back(cchar); //makes a temporary string, copies the string into vector storage using push_back(const T&) v.push_back(std::string(cchar)); //makes a temporary string, moves the string into vector storage using push_back(T&&) v.push_back(std::move(cchar)); //makes a temporary string, moves the string into the vector using push_back(T&&)

Johannes Schaub (litb) convincingly argued that the reason for this is clause 8.5.3/5 describing reference binding - it allows direct binding of lvalues, bindings that require conversion sequences to const lvalue refs, and rvalues to rvalue refs. But it doesn't allow for lvalues to ever bind to rvalue refs, even if an intermediate temporary would otherwise need to be created.

This isn't what I (as a user of std::vector) expect to happen. I expect all of these push_back calls to do the same thing, namely, select the push_back(T&&) overload, create a temporary string object from 'cchar', bind the temporary string to the argument, and hence move (not copy) the temporary string into vector's storage. It seems particularly strange that v.push_back(cchar) "requires" an extra copy, but v.push_back(std::move(cchar)) does not. It almost seems like indicating that 'cchar' is potentially-movable (by casting it to an rvalue ref using std::move) allows moving from a completely different object - the temporary string.

I suggest extending the rules for initializing const lvalue refs via implicit conversions (8.5.3/5), to also apply to rvalue refs.

This also raises an additional question of whether lvalues of _copyable_ types should be copied into a temporary object so that they may bind to an rvalue ref. Allowing this would not affect const T&/T&& overload pairs. But it could be potentially useful when writing functions that wish to accept a number of rvalue refs to copyable-but-not-movable types (such as all C++03 classes with user-defined copy constructors), or when writing functions that "take apart" a number their arguments in a way that is different from a straightforward move (perhaps some tree operations would want to do this). Conversely, it might seem odd that declarations such as:

string && s = string_lvalue; string && s = string_rvalue_ref_variable; //mistake, std::move(string_rvalue_ref_variable) was intended

...would both silently copy their arguments and bind to the copy, instead of being invalid as they are now.

Possible wording: amend the second list item in 8.5.3/5: Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference [deleted the rest of the sentence]. [The last example would also need to be deleted.]
by Douglas Turk at 15:00:33 on Monday, 21 January 2019

&#167;1.10/3 doesn't specify any temporal link between the two expression evaluations. I suggest that the text be changed to something like, "Two expression evaluations conflict if one of them modifies a memory location *while* the other one accesses or modifies the same memory location."

by Rob Stewart at 15:00:33 on Monday, 21 January 2019

Did we get variable sized arrays (with const size initializer) as class members?

PLEASE tell me we did!
by zerothat at 15:00:33 on Monday, 21 January 2019

Add your comment

Your name:

Email address:

Your comment:

Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy