Travis CI

Configuration for C++, Python, R, bash and Graphviz

Note: my use of Travis CI has been superseded by GitLab which has all this built in. In fact this blog is generated by GitLab. Create an account with your GitHub login and enable a repo to get started. (Travis Pro appears to enable new repos by default.) Simple C++11 compilations If you just want to get something building quickly the default Trusty build has clang 5 pre-installed, no need for complicated matrices. [Read More]

Exceptions in destructors

In C++11 destructors default to noexcept so you have to go out of your way to make them throw. See throwing a vector in a destructor. #include <exception> #include <iostream> #include <vector> // Note the braces void exception1() try { throw 1; } catch (int e) { std::cout << "Caught " << e << std::endl; } catch (const std::out_of_range &oor) { std::cout << "Caught OOR\n" << oor.what() << std::endl; } catch (const std::exception &e) { std::cout << "Caught " << e. [Read More]

STL containers Sequence Containers array vector deque forward_list list Container Adapters stack queue priority_queue Associative Containers set map multiset multimap Unordered Associative Containers unordered_set unordered_multiset unordered_map unordered_multimap Features multiset, set and map are typically implemented as binary search trees. Forward lists are sequence containers that allow constant time insert and erase operations anywhere within the sequence. map is generally slower than unordered_map containers to access individual elements by their key, but it allows the direct iteration on subsets based on their order. [Read More]


Argument dependent lookup

Why does this compile? A one-liner to print a vector to stdout. But why does this compile without the namespace std::? #include <iostream> #include <vector> #include <iterator> int main() { const std::vector<int> v{1, 2, 3, 4, 5}; copy(cbegin(v), cend(v), std::ostream_iterator<int>(std::cout, "\n")); } Run the code on Compiler Explorer, Jason Turner on YouTube and ADL on Wikipedia. Note: C++14 is the default for the latest GCC (9.2). Exercise Propose some other examples of ADL. [Read More]

Modern C++

lvalues and rvalues An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it. A function call can be an lvalue if and only if the return value is a reference. [Read More]


A Linux JUCE application that extracts the peak FTT bin from a live audio recording and reports the closest note

Screenshot is highlighting the major 3rd of an A chord: 440, 550 and 660Hz. Note the FFT bin is not a precise pitch so the closest concert pitch is displayed. See the source on GitHub. Note mapping #include <iostream> #include <map> #include <vector> const std::map<double, std::string> notes{ // Catch all for lower bound search {0.0, "Bx"}, // All the notes we're interested in. At the low end a single Fourier bin // will map to multiple notes. [Read More]

How does your vector grow?

How many times is the destructor for the “fax” class called below after populating a five element STL vector? std::vector<fax> y; for (size_t i = 0; i < 5; ++i) y.push_back(fax()); Remarkably it’s 17 times! Run the code on compiler explorer. For each push we call the default constructor to create a transient object and then call the copy constructor to populate the new element with its data. So far so good. [Read More]

Bird in a bird

How many times is the destructor called?

struct bird { ~bird() { std::puts("in a bird"); } }; bird in = bird(bird(bird(bird(bird())))); The destructor is called once! Thanks to C++’s return value optimisation. You can disable this behaviour by passing -fno-elide-constructors to the compiler. However, if you’re using a standard later than C++14 then it happens regardless. So does this mean we can’t let copy constructors cause side-effects, lest the compiler doesn’t bother calling them? See copy elision and run the example in Compiler Explorer. [Read More]

Modern C++ migration

Welcome to the std::promised land

Auto Type inference is a game changer. Essentially you can simplify complicated (or unknown) type declarations with auto. But it can be a balance of convenience over readability. int x1 = 5; // Explicit auto x2 = 5; // What's the underlying literal type? std::vector<std::string> moon = {"Don't", "look", "at", "the", "finger"}; auto finger = moon.front(); And there are a few perfectly valid gotchas. Let’s create a variable and a reference to it, updating y2 (below) also updates y1 as expected. [Read More]