Knowledge Base/CPP/General
From Quantitative Finance
Statically detecting the Visual Studio version
#if _MSC_VER >= 1500 // Visual Studio 2008 or above #elif _MSC_VER >= 1400 // Visual Studio 2005 #elif _MSC_VER >= 1310 // Visual Studio 2003 #elif _MSC_VER > 1300 // Visual Studio 2002 #endif
Convert an enum into an int. Convert an int into an enum
For enums, there is an implicit conversion to int:
enum Quarter {FIRST=1, SECOND=2, THIRD=3, FOURTH=4}; int q = FIRST;
For ints, there is an explicit conversion to enum:
enum Quarter quarter; quarter = static_cast<Quarter>(2);
Testing an integer's even- or oddness
if (n & 1) ...
Doubling a positive integer
n <<= 1;
An algorithm for determining whether a function should be a member and/or friend
Use the following algorithm due to Herb Sutter and Andrei Alexandrescu to determine whether a function should be a member and/or friend (C++ Coding Standards: 101 Rules Guidelines and Best Practices, Item 44: Prefer writing nonmember nonfriend functions):
// If you have no choice then you have no choice; make it a member if it must be:
If the function is one of the operators =, ->, [], or (), which must be members:
Make it a member.
// If it can be a nonmember *non*friend, or benefits from being a nonmember friend, do it:
Else if:
a) the function needs a different type as its left-hand argument
(as do operators >> and <<, for example);
or b) it needs type conversions on its leftmost argument;
or c) it can be implemented using the class's public interface alone:
Make it a nonmember.
If it needs to behave virtually:
Add a virtual member function to provide the virtual behaviour,
and implement the nonmember in terms of that.
Else
Make it a member.
Implementing a non-const function in terms of the correpsonding const function
It is possible to implement a non-const function in terms of the corresponding const function as follows:
const S & T::foo() const { // ... } S & T::foo() { const T * cthis = this; return const_cast<T &>(cthis->foo); }
This technique, suggested by Siemel Naran, involves a const_cast.
Implementing the postfix operator++ in terms of a prefix operator++
// Prefix T & operator++() { // ... Perform the increment ... return *this; } // Postfix const T operator++(int) { T temp = *this; ++*this; return temp; }
Notice that (int) is used to distinguish between the prefix and postfix versions of the operator.
Similarly for operator--:
// Prefix T & operator--() { // ... Perform the increment ... return *this; } // Postfix const T operator--(int) { T temp = *this; --*this; return temp; }
Implementing operator= in terms of a (no fail) swap
The following definition of operator= in terms of a copy constructor and a no fail swap is idiomatic. swap is needed for a guaranteed commit. It must not fail. It must never throw exceptions.
T & T::operator=(const T & rhs) { T temp(rhs); noFailSwap(temp); }
Implementing operator@ in terms of operator@=
Where @ is a binary operator such as +, *, etc. This is generally a very good idea, consistent with the Principle of Least Surprise.
The non-member case: operator@ and operator@= are non-members
T & operator@=(T & lhs, const T & rhs) { // ... return lhs; } T operator@(T & lhs, const T & rhs) { // Note that lhs is taken by value return lhs @= rhs; }
The member case: operator@ and operator@= are members
T & operator@=(const T & rhs) { // ... return *this; } T & operator@(const T & rhs) { T temp(*this); temp @= rhs; return temp; }
Implementing operator!=, operator>, operator<=, operator>= in terms of operator== and operator<
We want to enforce consistency and avoid code repetition. Therefore we define operator== and operator<...
inline bool operator==(const T & lhs, const T & rhs) { // ... } inline bool operator<(const T & lhs, const T & rhs) { // ... }
...then implement the remaining relational operators in terms of the above, as follows:
inline bool operator!=(const T & lhs, const T & rhs) { return !(lhs == rhs); } inline bool operator>(const T & lhs, const T & rhs) { return rhs < lhs; } inline bool operator<=(const T & lhs, const T & rhs) { return !(rhs < lhs); } inline bool operator>=(const T & lhs, const T & rhs) { return !(lhs < rhs); }
Erase-remove idiom
The erase-remove idiom is the best way to remove elements with a specific value from a contiguous-memory container (e.g. a vector, string, or queue).
c.erase(remove(c.begin(), c.end(), 1666), c.end());
For lists, the remove member function is more efficient:
c.remove(1666);
For associative containers one must use the erase member function:
c.erase(1666);
The "swap" trick to lop off the empty (reserved) space at the end of a vector or string
vector<Widget> v; string s; // ... // Use v and s // ... vector<Widget>(widgets).swap(v); string().swap(s);
Inserting a key-value pair into a map efficiently
someMap.insert(map<T, U>::value_type(someT, someU));
Looking up an element in a map while avoiding default element insertion
If you use the subscript syntax to access a map element as follows
string fooValue = someMap["foo"];
a new element will be inserted if the key "foo" is not already in the map. The corresponding value will be default-initialised. If you want to avoid this insertion, use the following:
map<string, string>::iterator iter = someMap.find("foo"); if (iter != someMap.end()) { fooValue = iter->second; }
Inserting an element into a set if it does not already exist
If we need to insert a new element into a set provided it doesn't already exist in the set, and deal with the consequences if the element already exists, we can use the following paradigm:
pair<set<string>::iterator, bool> status = someSet.insert("foo"); if (! status.second) { // The element wasn't inserted as it already existed in the set // ... }
Inserting an element into a map if the key does not already exist
If we need to insert a new element into a map provided the key doesn't already exist in the map, and deal with the consequences if the key already exists, we can use the following paradigm:
pair<map<string, string>::iterator, bool> status = someMap.insert(pair<string, string>("foo", "bar")); if (! status.second) { // The element wasn't inserted as the key already existed in the map // ... }
It is worth noting that if we had someMap["foo"] == "baz" before the above code was executed, someMap["foo"] would not be overwritten.
Passing arrays to functions that expect iterators
Suppose you have the following function:
#include <iterator> #include <numeric> template <typename _IterT> typename iterator_traits<_IterT>::value_type sum(_IterT from, _IterT to) { return accumulate(from, to, 0); }
You want to pass an array to it. You can do it as follows:
template <typename _Data, typename _Size = size_t> _DataT sum(const _Data * data, Size N) { return sum(data, data + N); }
Adding up the element counts in a vector of vectors using std::accumulate and Boost lambda abstractions
Suppose that you have a collection of collections, e.g. a vector of vectors. You want to count all the elements in this structure (i.e. add up the sizes of the contained vectors). You can achieve this by using std::accumulate and Boost lambda abstractions:
#include <iostream> #include <numeric> #include <vector> #include <boost/lambda/bind.hpp> #include <boost/lambda/lambda.hpp> using namespace std; using namespace boost::lambda; void columnCountProto() { typedef vector<double> VectorOfDoubles; typedef VectorOfDoubles::size_type SizeType; typedef vector<VectorOfDoubles> VectorOfVectorsOfDoubles; VectorOfVectorsOfDoubles vectorOfVectors; VectorOfDoubles v1; VectorOfDoubles v2; VectorOfDoubles v3; VectorOfDoubles v4; VectorOfDoubles v5; v1.push_back(1.0); // 1 v1.push_back(2.0); // 2 v2.push_back(3.0); // 3 v2.push_back(5.0); // 4 v2.push_back(7.0); // 5 v3.push_back(10.0); // 6 v5.push_back(0.0); // 7 vectorOfVectors.push_back(v1); vectorOfVectors.push_back(v2); vectorOfVectors.push_back(v3); vectorOfVectors.push_back(v4); vectorOfVectors.push_back(v5); cout << "vectorOfVectors size: " << vectorOfVectors.size() << endl; SizeType elementCount = accumulate( vectorOfVectors.begin(), vectorOfVectors.end(), SizeType(0), _1 + bind(&VectorOfDoubles::size, _2)); cout << elementCount << endl; }
This displays "7", as expected.
What about finding the maximum count, rather than the sum? Use the following code instead:
SizeType maxElementCount = accumulate( vectorOfVectors.begin(), vectorOfVectors.end(), SizeType(0), bind(Maximum<SizeType>(), bind(&VectorOfDoubles::size, _2), _1)); cout << maxElementCount << endl;
This will display "3" (due to v2, which contains three elements).
By the way, here Maximum is defined as follows:
template <typename _Type> struct Maximum : public binary_function<_Type, _Type, _Type> { _Type operator()(_Type first, _Type second) const { return (second > first) ? second : first; } };
Note that the Standard Library defines the two template functions std::min and std::max in the <algorithm> header, but Visual Studio C++ does not define these function templates as per Danny Kalev's comment. If std::max is available, you can use it instead of the Maximum above.
Remember that accumulate is defined in the header file <numeric>, not <algorithm>.
Along the same lines you can use for_each to clear the contained vectors in a vector of vectors:
for_each(vectorOfVectors.begin(), vectorOfVectors.end(), bind(&VectorOfDoubles::clear, _1));
You can also reserve some space in all of them, say enough space for ten doubles:
for_each(vectorOfVectors.begin(), vectorOfVectors.end(), bind(&VectorOfDoubles::reserve, _1, 10));
We can also construct a vector of iterators for the contained vectors, pointing to their first elements ("begin"):
vector<VectorOfDoubles::iterator> vectorOfIterators; transform( vectorOfVectors.begin(), vectorOfVectors.end(), back_inserter(vectorOfIterators), bind(boost::mem_fn(&VectorOfDoubles::begin), _1));
