5 ms·
C++ concepts support merged into GCC trunk
- qznc 11y agoAfter watching this talk [0] by Andrei Alexandrescu, I became somewhat sceptical about concepts (and type classes and traits). Nevertheless, it's probably an improvement for C++. [0] https://www.youtube.com/watch?v=mCrVYYlFTrA https://www.youtube.com/watch?v=mCrVYYlFTrA
- enqk 11y agoCan you summarize what you found convincing about his presentation? The narrative of the presentation is him focusing on a case where they don't work and tries to claim they never work. His pretty brash conclusions do not follow from his "demonstration"
- qznc 11y agoI tried to document my insight here: http://beza1e1.tuxen.de/articles/interface_fail.html http://beza1e1.tuxen.de/articles/interface_fail.html Concepts probably work for 80% of the cases and you can work around the rest intuitively. On the other hand, we might not have realized how some algorithms can be written even more generic with "static if".
- enqk 11y agoReally cool of you to document your insights, I wish more people would do that :)
- qznc 11y agoThanks. That is one of the essential elements of blogging for me. It allows me to link to larger text from short comments. ;)
- enqk 11y agoI revisited the concepts pdf (which can be found in the original post) and it has a `requires` statement, which allows to combine multiple constraints on the types of a templated construction. This would allow to write (your `Cloneable Iterator` idea) template <ForwardIterator T> requires CopyConstructible<T> void copy(T a, T b) Java Interfaces and C++ Concepts: the later being much more open, and Java interfaces being closed under types (C++ requires statement can have boolean const expressions in them) I think the definition of good concepts is going to be hard that is for sure, however when one find a good one (one that can be shared within a programming community the way mathematical concepts are shared) then it will convey just the right amount of information for a community to understand the code they share.
- kirab 11y agoI'm really glad that concepts are finally making their way in after such a long time. Concepts make using and developing templates so much more straight-forward and easier to read!
- pmr_ 11y agoHow do you know that? Have you had any practical experience with a large code base using new style (e.g. post-C++11) Concepts? People have been using Concepts in some form for a very long time and even properly documented they can still be a major hurdle to less advanced or interested users.
- cshimmin 11y agoFor others like me who have been living under a rock: https://en.wikipedia.org/wiki/Concepts_(C%2B%2B) https://en.wikipedia.org/wiki/Concepts_(C%2B%2B)
- jokoon 11y agoSo their primary function is to make template error messages more readable, by giving tools to the programmer to be more specific when defining template types? I really need to see a comparison with examples that shows that it's interesting to use, if I remember template metaprogramming was not an intended use, so are concepts redirecting the language to saner places ? It seems like it could be beneficial for certain specific software like math software (maybe AI or language software ?), but other than that I feel very unable to grasp concepts. Maybe a CS teacher could explain it better to me. Again, can't wait for Effective C++ to cover those, but a slight introduction would not hurt :)
- alepper 11y agoConstraints on template types are useful outside of metaprogramming proper. For example, the standard library already specifies classes of iterators dependent on e.g. the direction(s) in which they may be advanced.
- maxlybbert 11y agoConcepts were supposed to be one of the big features of C++11. They weren't going to make templates more efficient, but they would make working with templates a little easier. Eventually, they became unwieldy, and they made compilation times much worse. The Committee had the pressure to ship and fix it later that Hoare talked about in his Turing Award lecture ( http://www.cs.fsu.edu/~engelen/courses/COP4610/hoare.pdf http://www.cs.fsu.edu/~engelen/courses/COP4610/hoare.pdf ). Surprisingly, they resisted Hoare's "mad dash" and deferred concepts. This article is about a stripped-down version of concepts that was accepted into the upcoming version of C++. It's supposed to have most of the benefits of the C++11 proposal, without the complexity. But I have to admit that the main benefits are better error messages, explicit comments in code of what a template requires, and an additional syntax for declaring/defining templates. The C++11 proposal was more exciting, but there was a question of whether it went too far.
- smegel 11y agoSo type checking for thing inside the <> as well as the ()?
- okasaki 11y agoLooks like Haskell's type classes.
- srean 11y agoIt is.
- repsilat 11y agoI think so. I figure C++ has a static type system in most places because it helps the language be fast -- resolving the target of a method call at compile time turns it into a straight function call, and straight function calls can be inlined etc etc. You know how big your objects might be, so you can put them on the stack and you can copy them back and forth. Templates give you a limited kind of polymorphism without sacrificing all of this nice stuff. Compilation of templates is "interpreted", though -- you don't compile a program to quickly instantiate them, you don't JIT them, the data structure just keeps data structures in memory along with its ASTs and it iterates over them, doing its type-checking and everything else "the slow way". I guess C++ compilation looks a lot like Python interpretation, with "No candidate for operator<(const T)&" standing in for AttributeError, and pages of horrible template messages standing in for tracebacks. This analogy raises a question, though -- if Python doesn't need type checking to get nice error messages, why do C++ templates? An alternative to "assert hasattr(a, '__cmp__')" is try-catch. Why not do the same with std::sort? Put a big compile-time try-catch around it, catch your template errors and present a nice message to your users. What benefits would this have over type checking? If anyone wrote their concept specifications too strictly, they might stop your valid program from compiling, and this wouldn't happen with static try-catch. Maybe they thought you needed a random access iterator when all you needed was a forward iterator. What benefits might concepts provide? Same as regular type checking -- if you know that the provided type has to present a given interface, you probably do something crazy like give your compile-time types vtables for the interface, and dramatically speed up compilation times. I don't know that anyone will actually do anything like this, though.
- jahnu 11y agoIs this just for experimentation or is it planned that this will be more or less the solution that makes it into the standard?
- octoploid 11y agoIt is not just for experimentation. The implementation is the basis of a Technical Specification, that will hopefully make it into C++17. Finally the TS will be merged into the standard in the further future.
- adamzubi700 11y agohttp://googler700.blogspot.com/2015/08/c-file-programs.html http://googler700.blogspot.com/2015/08/c-file-programs.html
- emcrazyone 11y agoLike others I was struggling to find usefulness of this and what problems it solves. I admit, it seems like a stretch. There was a situation in which I needed a template class to be implemented such that I wanted only certain types to be accepted one way and others a different way. I implemented a stream buffer that can accept different types into the stream. Based on the type, the buffer would serialize and expand to accept the data. To put this more succintly, an insert of unit8_t type would put a single byte into the stream buffer and an insert of uint16_t would put two bytes into the stream buffer. And I needed a way to make sure the types were plain old data types (int, char, uint8_t, uint16_t, uint_32_t, etc...) Here is sample code: template<typename T> class TStream { private: typedef TBuffer<T> stream_buffer; stream_buffer mStream; public: TStream(); TStream(const TStream &rhs); TStream::~TStream(); unsigned int Size() const; unsigned int ByteStreamLength() const; void Clear(); // some methods omitted for brevity const T&operator[](unsigned int idx); const T*operator[](unsigned int idx) const; TStream<T> &operator=(const TStream &rhs); TStream<T> &operator=(T const); TStream<T> &operator=(unsigned char); TStream<T> &operator=(bool); TStream<T> &operator=(double); // rest omitted for brevity }; Doing this TStream<unsigned char> ByteStream causes ambiguity with operator=(unsigned char). I basically want operator=(unsigned char) to be omitted if T = unsigned char. The way I solved this, without Concepts of course, was to use CRTP like so: template<typename D, typename T, typename U> struct implement_operator_plus_equals { implement_operator_plus_equals() { static_assert(std::is_base_of<implement_operator_plus_equals, D>::value, "CRTP failure" ); } D* self() { return static_cast<D>(this); } D const self() const { return static_cast<D const>(this); } typedef D Self; Self& operator+=( U u ) { static_assert( (sizeof(U)%sizeof(T)) == 0, "Non integer number of Ts in a U" ); T* b = reinterpret_cast<T*>(&u); T* e = b + sizeof(U)/sizeof(T); for (T* it = b; it != e; ++it) { self()->consume(*it); return *self(); } }; template<typename D, typename T> struct implement_operator_plus_equals<D,T,T> { implement_operator_plus_equals() { static_assert( std::is_base_of<implement_operator_plus_equals, D>::value, "CRTP failure" ); // Have an operator+= that cannot be called, so using ...::operator+= is legal, // but mostly harmless: class block_call {}; void operator+=( block_call ) {} } }; I believe I could have solved this without CRTP using Concepts. Although my understanding is that Concepts follows a methodology of deny all, allow what is defined and there appears to be no way to allow all, deny what is specified as a Concept. In other words, Concepts only tell the compiler what is allowed and there appears to be no way to specify what is NOT allowed without some further "trickery."