C++: Unexpected Behaviour - Antonio Mallia, Jaime Alonso
New video from Meeting C++ 2017!
C++: Unexpected Behaviour
by Antonio Mallia and Jaime Alonso
February 10-15, Hagenberg, Austria
March 19-21, Madrid, Spain
April 1-4, Bristol, UK
June 16-21, Sofia, Bulgaria
By Meeting C++ | Feb 15, 2018 03:02 AM | Tags: meetingcpp intermediate
New video from Meeting C++ 2017!
C++: Unexpected Behaviour
by Antonio Mallia and Jaime Alonso
By Meeting C++ | Feb 13, 2018 05:41 AM | Tags: tools meetingcpp intermediate efficiency dependencies
New talk from Meeting C++ 2017!
Dealing with software dependencies
by Kiki de Rooij & Peter Bindels
By Adrien Hamelin | Feb 12, 2018 10:55 PM | Tags: intermediate
Good question.
To RAII or Not to RAII?
by Jonathan Boccara
From the article:
RAII is a central concept in C++, that consists in relying on the compiler to call destructors automatically in certain cases. Putting appropriate code in such destructors then relieves us from calling that code – the compiler does it for us.
RAII is an idiomatic technique of C++, but can we use RAII for everything? Is it a good idea to shift every possible piece of code to the destructor of some class, to leave the work to the compiler and make calling code as light as can be?
Since this question comes down to asking if the proverbial hammer is a tool fit for every single task, the answer to that question is probably the proverbial No.
But then, in which cases would RAII improve the design of a piece of code?
In this article we’ll see a case where RAII is adapted, then a case where RAII is NOT adapted. And after that we’ll see a case open to discussion. We’ll then conclude with how to use levels of abstractions to make the decision to RAII or not to RAII...
By Meeting C++ | Feb 9, 2018 06:38 AM | Tags: meetingcpp intermediate c++14
A new talk from Meeting C++ 2017:
Reactive Equations
by André Bergner
By Meeting C++ | Feb 8, 2018 07:31 AM | Tags: meetingcpp intermediate algorithms
New Video from Meeting C++ 2017!
Fantastic Algorithms and Where To Find Them
by Nicholas Ormrod
By Adrien Hamelin | Feb 7, 2018 07:23 PM | Tags: intermediate c++11
Quick A: If there is an initializer list contructor, it will choose it.
Recently on SO:
Direct initialization with empty initializer list
When an argument is an initializer list ([dcl.init.list]), it is not an expression and special rules apply for converting it to a parameter type.
If the parameter type is std::initializer_list or “array of X” and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X. This conversion can be a user-defined conversion even in the context of a call to an initializer-list constructor.
Otherwise, if the parameter is a non-aggregate class X and overload resolution per [over.match.list] chooses a single best constructor of X to perform the initialization of an object of type X from the argument initializer list, the implicit conversion sequence is a user-defined conversion sequence. If multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence. User-defined conversions are allowed for conversion of the initializer list elements to the constructor parameter types except as noted in [over.best.ics].
By Adrien Hamelin | Feb 7, 2018 07:20 PM | Tags: intermediate c++11
Quick A: If you have an object which should never, ever be deleted or stored on the stack (automatic storage), or stored as part of another object, =delete will prevent all of these.
Recently on SO:
Uses of destructor = delete;
struct Handle { ~Handle()=delete; }; struct Data { std::array<char,1024> buffer; }; struct Bundle: Handle { Data data; }; using bundle_storage = std::aligned_storage_t<sizeof(Bundle), alignof(Bundle)>; std::size_t bundle_count = 0; std::array< bundle_storage, 1000 > global_bundles; Handle* get_bundle() { return new ((void*)global_bundles[bundle_count++]) Bundle(); } void return_bundle( Handle* h ) { Assert( h == (void*)global_bundles[bundle_count-1] ); --bundle_count; } char get_char( Handle const* h, std::size_t i ) { return static_cast<Bundle*>(h).data[i]; } void set_char( Handle const* h, std::size_t i, char c ) { static_cast<Bundle*>(h).data[i] = c; }Here we have opaque Handles which may not be declared on the stack nor dynamically allocated. We have a system to get them from a known array.
I believe nothing above is undefined behavior; failing to destroy a Bundle is acceptable, as is creating a new one in its place.
And the interface doesn't have to expose how Bundle works. Just an opaque Handle.
Now this technique can be useful if other parts of the code need to know that all Handles are in that specific buffer, or their lifetime is tracked in specific ways. Possibly this could also be handled with private constructors and friend factory functions.
By Meeting C++ | Feb 2, 2018 03:40 AM | Tags: meetingcpp intermediate algorithms
A great introduction to some lesser known algorithms:
Fantastic Algorithms and Where To Find Them
by Nicholas Ormrod
By Adrien Hamelin | Jan 31, 2018 07:14 PM | Tags: intermediate c++17
And make less mistakes.
Help the compiler warn you
by Andrzej Krzemieński
From the article:
Compiler warnings are a very useful tool for detecting bugs in your program. Because you can enable them selectively, and because you can choose to turn them into hard errors on your compiler, you can in fact build a dialect, which is a safer subset of C++...
By Adrien Hamelin | Jan 31, 2018 07:12 PM | Tags: intermediate community
A classic error:
break and fallthrough
by Andrey Karpov
From the article:
We would like to suggest reading the series of articles dedicated to the recommendations on writing code of high quality using the examples of errors found in the Chromium project. This is the second part, which will be devoted to the switch operator and, more precisely, to the problem of a forgotten break operator...