C++ Papers for Chicago: Part 2 - Core, Concepts & Evolution
published at 16.09.2013 12:59 by Jens Weller
Save to Instapaper Pocket
Welcome to the 2nd part of this little papers series. The first part covered the papers on concurrency. This time I cover core, concepts, evolution and filesystem. I decided to keep the format with grouping the papers by domain, it makes it easier to have an overview. This edition focuses on the papers of the evolution subgroup, and also features the two highlights concepts and filesystem, which are their own subgroups and have submitted each one paper in July. Last time I did not cover filesystem, but concepts, so I'm looking forward to look deeper into features coming into C++.
Most of the papers will become part of C++ after C++14, there is the next standard yet dubbed C++1y, which could become C++17, before things sharpen for C++17, most subgroups are going to issue technical specifications, which then might be accepted into the standard. Some vendors might offer implementations of those TS, most likely starting with filesystem. More and more people are coming to the committee meetings, more and more companies see the value of the C++ standard, so that a lot of things will change before we see C++17 take shape. The draft for C++14 after Bristol shows that with the next standard only minor changes and a lot of improvements will come to C++. But lets go to the papers, I oversaw one paper on concurrency, so lets get started with that one:
N3706 - C++ distributed Counters
This proposal would like to add distributed counters to C++. The presented implementation is a library of counter classes and helper classes to ease parallel counting. The background is, that in parallel programs, the pattern to maintain certain counters is a common need. The proposed counter is trimmed to be optimized on the counting operations (e.g. writes), and make read more expensive.
N3701 - Concepts Lite
Concepts was once thought to be the flagship of C++11, but was dropped, as it turned out to be as a feature just too heavy. Still, C++ should have some way of constraining templates to a certain form of concepts. There is a talk about concepts lite at my Meeting C++ 2013 conference from Peter Sommerlad, which will go more into the details, then I can here.
This paper is the current approach, a much lighter version of concepts. Concepts Lite is currently implemented as a branch of GCC 4.9, and the authors claim that concepts lite:
- allows programmers to directly state the requirements of a set of template arguments as part of a template’s interface
- supports function overloading and class template specialization based on constraints
- seamlessly integrates a number of orthogonal features to provide uniform syntax and semantics for generic lambdas, auto declarations, and result type deduction
- fundamentally improves diagnostics by checking template arguments in terms of stated intent at the point of use, do all of this without any runtime overhead or longer compilation times
The paper is in its 2nd version, therefore the authors state that the major changes are:
- the syntax for constrained member functions and the requires expression has changed
- the authors introduce a new syntax allowing to constraint generic lambdas and allows to use constraints wherever auto is used
- overload sets are now allowed for constraint functions
- the standards wording has been improved, but does not yet include constrained generic lambdas
A short example how concepts lite could look like:
template<Sortable Cont> void sort(Cont& container);
Here, Sortable is the constraint. It is in this case defined to require a random access iterator and the operator<. The Sortable constraint acts as type of Cont here, but is defined else where. So this is not the definition of a constraint, it is the use of a constraint. A alternative syntax allows to specify the constraints more exactly with require:
template<typename Cont> requires Sortable<Cont>() void sort(Cont& cont)
This allows to explicit state the requirements for a template after its interface definition. A constraint is now defined as:
"A constraint is a function template declared using the declaration specifier, concept. The concept specifier implies that the declaration is constexpr, and it enforces some other restrictions. In particular, concepts must not have function arguments, and the must return bool."
So, a more complex constraint definition could look like this:
template<typename T> concept Equality_comparable() { return has_eq<T>::value && is_convertible<eq_result<T>,bool>::value && has_ne<T>::value && is_convertible<ne_result<T>,bool>::value; }
To aid the implementation of concepts, the authors also introduce a way to implement constraints as a requires expression:
template<typename T> constexpr bool Equality_comparable() { return requires (T a, T b) { bool = {a == b}; bool = {a != b}; }; }
The paper goes on further into the details of implementing a concept lite approach. Even concepts lite brings a lot of changes to the language, so that if it makes into an upcoming standard, will change a lot how we interface with templates in C++. In Exchange error messages and the work with templates would improve a lot.
N3718 - Transactional Memory Support for C++
This paper is part of the evolution subgroup papers, featuring a look at how to integrate transactional memory into C++. The paper opts for integrating transactional memory as a language feature, a short example:
void transfer(Account a1, a2; int x;) { transaction_atomic noexcept { a1.withdraw(x); a2.deposit(x); } }
Here, the transaction is embedded into the code as a block, that can me marked as noexcept (not throwing) or as cancel_on_escape, so that the operation is rolled back, if an exception is thrown. There is also the transaction_relaxed available, for blocks of non atomic transactions. The paper also wants to add the qualifier transaction_safe or transaction_unsafe to functions, so that they can be marked accordingly.
N3723 - Extent operator-> to support rvalues
C++11 brought move semantics and rvalue references, but operator-> does not play very well with move semantics yet. In the current standard, operator-> cannot return an rvalue to a temporary constructed type. This can be useful when creating iteratorclasses, that construct an object out of several sources. The example in the paper constructs an iterator class from two arrays, where one array is x, and the other y positions, the operator-> then turns the current iterator position into a coordobject of coord(a[0],b[i]):
coord* operator->() { return &coord(a[0],b[i]); // invalid!!! }
In C++ this temporary could be turned into an rvalue, returned from the operator-> function. Then returning coord, instead of a pointer. A different, already working workaround would be to return a heap constructed object of coord inside of a unique_ptr.
N3725 - Original Draft Specification of Transactional Language Constructs for C++ Version 1.1
The updated version of the draft specification for transactional language constructs from February 3, 2012. This is directly related to N3718, just a bit longer and more specification like.
N3730 - Specializations and namespaces
This proposal aims at making things easier, at least for the user. Currently template specializations have to be in the same namespace, for example in std for std::hash. When doing so, one needs to close all open namespaces, open namespace std and specialize the template there. Then you reopen the previous namespaces to continue. The paper aims at allowing specializations in a bit of a different approach:
template<> struct ::std::hash { std::size_t operator()(C const &c) { /* ... */ } };
When the namespace is qualified in the template declaration, this should be a way to easily specialize types a lot easier, then currently possible. Separately, the paper suggests to allow the combined use of friend with this, making it possible to specialize templates as friends of a class. std::hash is an excellent example, std::less another one. The paper goes into a bit more details then I can here, I think its worth reading, if your interest in easing the use of C++ as a language.
I cannot get around to add a personal paragraph to this. With the bristol papers, there already was a paper aiming at template specializations and making them easier from Peter Gottschling, but in a different use case and more general relaxation. At Bristol, the time wasn't enough to look at this paper, I hope that there is more time for this in Chicago. This paper is a bit more concrete, and only pics one issue, so maybe it has a chance to make things a bit easier.
N3741 - Toward Opaque Typedefs for C++1Y, v2
In C++, typedefs are aliases, not types themselves. This leads to the situation, that one alias (or typedef) is interchangeable with another one. A function that takes a typedef as a parameter, will also accept all other typedefs for the underlying aliased type. The author proposes the following syntax using the using declarative for opaque typedefs:
using identifier = access-specifier type-id opaque-definition
So, using this is a bit more complex then typedef, the result would come close to BOOST_STRONG_TYPEDEF, which the paper also names as prior art. Last but not least, this should also be usable with templates, creating a template that is a opaque type. I like the idea, but I'm not sure if this is the right solution, but its an interesting way to solve this problem.
N3744 - proposing [[pure]]
A few papers surface from the past, this is one of them. While C++11 knows about nothrow, in its original origins, nothrow had also a brother, pure. This paper aims at introducing pure to C++14 or more likely C++1y. The authors conclude, that a function is pure, when
- it communicates with the client code only via the argument list and its return value
- and has no observable side effects.
A pure function is well-behaved. Examples from the standard library could be container::length, or std::hash<>::operator(). A pure function returns always the same value for the same set of parameters. The basic characteristics of a pure function would be that it takes its argument only by value or as const*/&/&&/const_iterator, and all modified values must be local to the function.
N3745 - Feature-testing recommendations for C++
Feature-testing for C++? Sounds like a nice idea, doesn't it? This paper tries to put up some recommendations for this:
"The more time that passes without any sort of feature-testing recommendation, the more confusion will affect programmers and implementers interested in features of C++14, of the sort that has plagued C++11 for years. So whatever action should be taken in this arena should not be delayed any more than can be avoided."
I like the idea of having a set of tests available for future standardization, but this paper is just a possible beginning for such thing as a C++ version test suite. The paper suggests, that for various features a #define of __cpp_feature_name or __cpp_lib_feature_name exists, so that code can be written using different versions of C++ and C++ features relying on the definition of the corresponding __cpp_ or __cpp_lib define. Further the paper suggests that you can test with __has_include for the presence of a certain header.
But this paper isn't as perfect as it sounds, various sections of it are stubs, that need to be defined. A nice thing that it already includes is a an overview over the C++14 features together with the testing defines for each feature. Not every feature has yet such a macro, but most do (at least in the paper). The stub sections still need to be filled though.
I want to emphasize, that having read most papers for Bristol, and now 30 - 40% for Chicago, this paper is different. It does not represent a new feature for the language instead, but tries to change ways and processes how things work in C++ Standardization. I like this idea a lot, having the ability to test in code for certain features would be great. Also the acknowledgment for testing inside the standard and its features, could help a lot when C++ moves forward to the coming standards of C++14, C++1y and everything what comes afterwards. C++ is changing from a statically (dead) standardized language to a faster moving standardized language, so we need the facilities to ensure that implementations are correct and the ability to test for certain features.
N3746 - Proposing a C++1Y Swap Operator, v2
This is the feature, where some people thought it was an early April fools joke. Its not. Its still alive, and in version 2. The basic idea is to add an operator:=: to C++, which acts as an operator for swapping. As the title suggests, this would be a features being added after C++14 (or even later). The basic proposed issue is, to add an operator for std::swap to the language, so that you could write a :=: b; for swapping a with b. The authors conclude:
"This paper has proposed a swap operator, operator:=: , for addition to C++1Y and has further proposed its application, where viable, as an alternative implementation technique for defaulted class assignment operators. We invite feedback from WG21 participants and other knowledgeable parties, and especially invite implementors to collaborate with us in order to experiment and gain experience with this proposed new language feature."
The advantage of an operator swap would be, that algorithms like std::sort could make use of a user defined implementation of such an operator.
N3748 - Implicit Evaluation of "auto" Variables and Arguments
The last paper from the Evolution subgroup. This time on the matter of improving auto. Sometimes, auto will not give you the type you expect, but the actual type of the expression. auto c = b * a; might result in c being a proxy type, expression template or a type used for inner representation in a library. Normal conversions to the expected type will not kick in. Now first - let me express my opinion - that auto is doing the right thing here, auto should just contain the type of an expression, and not have fancy things in the background happening. I think/hope the authors agree to this, so how to resolve this in a way that would make sense?
Well, this is where the idea of operator auto comes into play. The paper presents this idea with the example of having a matrix class, and a expression template class for multiplying matrices. When using auto on the expression a * b, right now, the result is the expression template, while actually the result, the matrix is the one wanted. The ability to specify the operator auto would improve this situation, where now the expression template can include an operator auto ensuring the conversion to matrix instead of holding the intermediate result type of the expression template.
As a side note, after C++Now 2013 I've met Andrew Sutton on the airport in Aspen, and we had a nice conversation starting at concepts lite going over to all sorts of C++ things, stopping by auto. I asked him in may - jokingly - about an operator auto, which he said could have its advantages. He could not explain it to me very well, but it was clear that something like this could exist in C++. This paper helped me to understand how and why an operator auto would make sense!
N3760 - [[deprecated]] attribute
This is the only paper from the core group. This paper is about marking things in C++ as deprecated. As C++11 finally added a standard syntax for attributes (before implementation defined, __attribute__ on gcc/clang and __declspec) on VC++), this paper aims at adding a standard attribute name deprecated.
An excerpt from the proposed wording:
"The attribute-token deprecated can be used to mark names and entities whose use is still allowed, but is discouraged for some reason. ... The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, an enumeration, or a template specialization."
Also it is proposed, that the attribute deprecated("can have a message attached to it"), which has the form of a string-literal.
N3693 - filesystem
The last series did miss out on filesystem, as the proposal for it was already part of the January mailing, which I did not cover for Bristol. As far as I understand, filesystem is based on the ideas behind boost::filesystem, and its 3rd version. As filesystem is its own subgroup, this represents not a single proposal, but a working draft for a technical specification. Also the working draft is still in its early stages.
So, the paper proposes a header <filesystem>, containing for example the path class. The pathclass is very important for filesystem, as its representing the basic building block of a filesystem: a path. A short overview over the classes of filesystem:
- path
- filesystem_error
- directory_entry
- directory_iterator
- recursive_directory_iterator
- file_status
- copy_options/directory_options (strong enums)
The paper specifies each class very detailed. There is a clear difference to boost::filesystem v3, the draft version is much more advanced into C++11 and also supports various string classes (string, wstring, utf8, u16/u32string). But the basic functionality is very similar to boost::filesystem. So most of the tutorial code of boost::filesystem should also be valid for filesystem. Filesystem will be released as a technical specification, and not into the C++14 standard, some vendors might already ship filesystem support accompanying C++14 thoug. With C++1y one can expect filesystem to be part of the standard.
Part 3 - papers from the Library Subgroup.
Join the Meeting C++ patreon community!
This and other posts on Meeting C++ are enabled by my supporters on patreon!