Skip to main content

C/C++

This page provides links to C++ resources as well as some information on compilers and the C++ language. There are also various code fragments and small projects making use of C or C++ on my Projects/Fragments page; the interested reader is encouraged to check them out and use anything they find interesting or useful.

Contents


Books

The following are, I would say, essential reading for anyone doing extensive work in C++. These are all in paper format.
Link key: [A] = Amazon, [W] = University of Warwick Library

  • The C Programming Language, 2nd Edition, Brian W. Kernighan & Dennis Ritchie (Prentice Hall, 1988) [A] [W]
  • The C++ Programming Language, Special (3rd) Edition, Bjarne Stroustrup (Addison Wesley, 2000) [A] [W]
  • C++ Templates, David Vandevoorde & Nicolai M. Josuttis (Addison Wesley, 2002) [A] [W]
  • Modern C++ Design, Andrei Alexandrescu (Addison Wesley, 2001) [A] [W]
  • Design Patterns, Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides (Addison Wesley, 1995) [A] [W]
  • Effective C++, Scott Meyers (Addison-Wesley, 2005) [A] [W]
  • More Effective C++, Scott Meyers (Addison-Wesley, 1995) [A] [W]
  • Effective STL, Scott Meyers (Addison-Wesley, 2001) [A] [W]
  • Exceptional C++, Herb Sutter (Addison Wesley, 1999) [A] [W]
  • C++ Template Metaprogramming, David Abrahams & Aleksey Gurtovoy (Addison Wesley, 2004) [A] [W]

If you're looking for an introductory C++ text, either for yourself or to recommend to students / others, I've heard good things about the following, but haven't read it myself (so please do not consider this to be anything like a personal endorsement; I'm merely passing on the recommendations of others!)

In general, I think it is fair to say that Addison Wesley publish a large number of extremely good books on C++ and related technologies, concepts and ideas. If you're looking for a book for a specific C++ topic, I'd highly recommend starting there.


Other Documents

The following links are to documents about C++ in various electronic formats.


Standards

The following specifications are internationally standardised; links are provided to the pages of the relevant standards bodies, and to Amazon if a bound version exists in print.

C++


C


Floating Point Arithmetic



More about C++11...

The C++ standard has recently been updated and approved by the ISO (as of August 12, 2011). The new version is known as C++11 (named after the year in which the standard was approved) and includes many updates to both the language and the library. C++11 was previously known as C++0x while the standardisation process was ongoing. The text below (in italic) is what I originally wrote about C++0x; much of this still holds, as compilers haven't yet fully caught up! C++11 is published as ISO/IEC 14882:2011.

The C++ standard is currently undergoing a major revision. The efforts are generally known as "C++0x" since the resulting standard was originally meant to be published sometime before 2009. Clearly it has taken longer, but the name stuck. There is a lot of information about the new features that C++0x provides; a good starting point is the Wikipedia entry. Some compilers currently support some of the C++0x features; a list is available at http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport. GCC is pretty much the best contender, right now.

In addition, there is a "first wave" of changes known as TR1. TR1 is a collection of additions to the C++ Standard Library (requiring only library modifications, no language modifications) roughly equivalent to the core Boost libraries. In fact, Boost provides a TR1 implementation which just forwards to the relevant parts of Boost itself. GCC also provides a TR1 implementation. For more information on TR1 look at either the Wikipedia page or the Boost TR1 library.


Websites

The following links are to useful resources for C and C++ programmers.


HEP Websites

The following sites are useful for C/C++ programmers within high energy physics (particle physics).


Compiler Warning Options

GCC (g++, the Gnu C++ Compiler)

GCC provides a large number of command-line options to enable warnings about different things. The set below covers a lot of the problematic areas; useful for checking that you're writing portable, well-formed code. If you can get your code to compile against these options, it's probably going to compile anywhere (within reason!)

I have the string below saved into a file called g++-warn-options so that when compiling I can do g++ `cat g++-warn-options` ...

-std=c++98 -pedantic-errors -Wall -Wextra -Werror -Wfatal-errors 
-Wwrite-strings -Woverloaded-virtual -fno-nonansi-builtins
-fno-gnu-keywords -fstrict-aliasing

Note that -Werror turns warnings into errors, forcing the compiler to stop even if the code would otherwise compile.

-Wshadow can also be used to warn about shadowing variables (defining variables of the same name in an inner scope). This is, however, a valid language feature, so the warning is best left out unless you didn't think you were using the feature, and want to be sure you're not!

Suggestions for additions to this list are welcome.

ICC (icpc, the Intel C++ Compiler)

The following list is a set of warning options for the Intel C/C++ compiler. The set below is fairly comprehensive; very little gets through without being noticed by these. Note that on the CSC Desktop, the Intel C++ Compiler is available by typing module load intel-cc

-Wall -Wcheck -Wuninitialized -Wunused-function -Wshadow -Weffc++ 
-Wcomment -Wextra-tokens -Wformat -Wformat-security -Wmissing-declaration
-Wmissing-prototypes -Wnon-virtual-dtor -Wpointer-arith -Wport -Wreorder
-Wreturn-type -Wstrict-prototypes -Wtrigraphs -Wunused-variable -Wwrite-strings


Operators

The list below defines the required / recommended form of operators when overloading for custom classes, etc. Rather than listing them all to begin with, I'll add a few every so often!

Comparison Operators

As non-member (possibly friend) functions, for a class X, or as member functions taking a single argument; a reference to the second object.

  • bool operator==(const X& a, const X& b);
  • bool operator<(const X& a, const X& b);
  • bool operator!=(const X& a, const X& b);
  • bool operator>(const X& a, const X& b);
  • bool operator>=(const X& a, const X& b);
  • bool operator<=(const X& a, const X& b);

Copy Assignment Operator

As a member function of X.

  • X& operator=(const X& a);

Streaming Operators

For a type X and standard iostreams; as free functions.

  • std::ostream& operator<<(std::ostream& stream, const X& obj);
  • std::istream& operator>>(std::istream& stream, X& obj);

Mathematical Operators

I called these "mathematical" because they should generally be used only where a mathematical definition makes sense. There are other uses, but it's generally considered a bad idea to give a class "math" semantics if it's not a mathematical quantity. There are two variants of these; the basic operation (e.g. x + 2), and operation-with-assignment, which sets the LHS equal to the result (e.g. x += 2). It's good practice to implement the former in terms of the latter, so I'll list the with-assignment versions first!

Operation-with-assignment; implemented as non-const member functions for a class X, taking a const reference to the RHS object, and returning a non-const reference to the object being operated upon (*this).

  • X& operator+=(const X& rhs); // addition with assignment
  • X& operator-=(const X& rhs); // subtraction with assignment
  • X& operator*=(const X& rhs); // multiplication with assignment
  • X& operator/=(const X& rhs); // division with assignment
  • X& operator%=(const X& rhs); // modulus (remainder) with assignment

Operation (no assignment). Usually implemented as non-member, non-friend functions taking two const X& arguments and returning an X.

  • X operator+(const X& lhs, const X& rhs); // addition
  • X operator-(const X& lhs, const X& rhs); // subtraction
  • X operator*(const X& lhs, const X& rhs); // multiplication
  • X operator/(const X& lhs, const X& rhs); // division
  • X operator%(const X& lhs, const X& rhs); // modulus (remainder)
  • X operator-(const X& operand); // unary negation (x --> -x)

Since "implemented in terms of" can sometimes cause confusion, here's an example for a trivial struct which wraps a single integer, providing addition:

struct MyInt {
int x;
MyInt& operator+=(const MyInt& rhs)
{
x += rhs.x;
return *this;
}
};

MyInt operator+(const MyInt& lhs, const MyInt& rhs)
{
MyInt temp(lhs);
temp += rhs;
return temp;
}


string.hpp

I wrote a header called string.hpp which provides some highly requested string processing features:

  • lstrip(), rstrip(), strip(): Return copies of a string with whitespace removed from the left, right or both.
  • lstrip_i(), rstrip_i(), strip_i(): Remove whitespace from left, right or both of a string, in place (i.e. editing the string passed-by-reference as an argument).
  • to_upper(), to_lower(): Return copies of a string with all characters converted to upper/lower case respectively.
  • to_upper_i(), to_lower_i(): Convert characters to upper/lower case in place (i.e. editing the string passed-by-reference as an argument)
  • class Tokenizer: Class to split a string into tokens based on some delimiter character.
  • tokenize(): Using Tokenizer class, return a vector of tokens based on a delimiter character.
  • string_to<T>(): Function to convert a string to a type T; uses stringstreams therefore requires that operator>> be defined for type T.
  • string_from<T>(): Function to convert T to a string; uses stringstreams therefore requires that operator<< be defined for type T.

Download string.hpp and a test program using the links below. Note that string.hpp is released under the terms of the BSD License. See the source files for details, or look at http://opensource.org/licenses/BSD-2-Clause.


CSVReader

The CSVReader project is a templated policy-based C++ class for reading from CSV files into arbitrary structures. It has its own page under my Projects section.


Mechanism for storing multiple cuts in a vector (where the value types and operations applied can differ for each cut)

This came about as a result of a discussion in the office. The problem was to have a vector of "cuts", each of which gives a boolean value depending on whether some quantity in an event meets some requirements, with some value used for comparison. Examples might include "number of hits > 200", "energy < 0.9 * largest energy in event", "spatial location within some volume". Each of these cuts requires a different type (int, float, geometry information [which might be a set of 3D points specifying limits]) and different operations (greater than, less than, contained within a 3D volume).

In order to store such things in a std::vector, they need to be of the same type (or have the same base type, so that you can store pointers to base). Furthermore, you ideally want to minimise the amount of code you have to write for each cut, and make sure that you can apply cuts to events by iterating over a vector and calling the same function; which implies virtual dispatch.

The solution I came up with (eventually) works something like this:

  1. Have a non-templated pure virtual base class with a virtual function bool apply(Event& e)
  2. Have a derived class, templated on the type of some CutFunctor, which inherits from the base class and implements apply(). More details on this later.
  3. Have a templated class for each kind of cut operation, e.g. GreaterThan (so you can have GreaterThan<int>, GreaterThan<float>), etc. which defines two things: a typedef of its template type -> ValueType, and bool operator()(Event& x, T& value);

Now, the Derived class, which is templated on some CutFunctor, can determine the value type through the CutFunctor::ValueType typedef, which means you don't have to rewrite any code in the Derived class for each type you want to use. It can also simply "forward" the apply() function to the CutFunctor's operator(), passing it the stored cut value and the reference to the current event. This means that no code in either the base (which is a pure virtual class) or derived (which is templated, and defers all the real work to a cut functor) class ever needs to be changed to implement a new kind of cut using any kind of type. Furthermore, since each instance of a Derived inherits from a common Base, you can store them in a std::vector<Base*>. The virtual dispatch ensures that (*iterator)->apply(evt); calls the correct Derived::apply() for the appropriate CutFunctor, and you need only write a new CutFunctor to add new functionality. Finally, the CutFunctor itself is templated so that (for instance) a generic "GreaterThan" can be applied to any type for which the > operator is defined.

Note, however, that the generality breaks down a little at this point; you have to extract the values you want from the event, which in this solution must be done inside CutFunctor::operator(). Of course, in practice you can just derive even further and make a TimeCut class which extracts the timestamp, then have TimeCutGreater and TimeCutLess...

  • Source code for the example: cuts.cc

Note that in the demonstration code, I use a typedef double Event; which simplifies the CutFunctor classes since they can use this value directly. This saved me having to define an Event class, but in reality you'd just extract the correct information from your event objects within the functor's operator().


Algorithms

The following algorithms are template functions designed to match the style used in the C++ Standard Library. Where appropriate, their names are based on the closest-matching standard library algorithm, and their template parameter types named in accordance with the standard library wherever possible.

transform_combinations

/*
 * Parameters:
 *  first1, last1
 *      Input iterators to the initial and final positions of the first sequence.
 *      The range used is [first1,last1), which contains all the elements between
 *      first1 and last1, including the element pointed by first1, but not the
 *      element pointed by last1
 *  first2, last2
 *      Input iterators to the initial and final positions of the second sequence.
 *      This sequence does not have to include the same number of elements as the
 *      first.
 *  result
 *      Output iterator to the initial position of the range where results are stored.
 *      The range includes as many elements as (last1-first1)*(last2-first2), or models
 *      an insert iterator.
 *  binary_op
 *      Binary function taking two elements as arguments, the first from the first
 *      sequence and the second from the second sequence (the types do not need to be
 *      the same), and returning some result value. Can be either a pointer to a
 *      function or an object whose class overloads operator().
 *
 *  Returns:
 *      An iterator pointing to the element that follows the last element written in
 *      the result sequence.
 * 
 */
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryOperator>
OutputIterator transform_combinations(InputIterator1 first1, InputIterator1 last1,
        InputIterator2 first2, InputIterator2 last2,
        OutputIterator result, BinaryOperator binary_op)
{
    for(InputIterator1 iter1 = first1; iter1 != last1; ++iter1)
    {
        for(InputIterator2 iter2 = first2; iter2 != last2; ++iter2)
        {
            *result++ = binary_op(*iter1, *iter2);
        }
    }
    return result;
}

Example:

#include <algorithm>
#include <cmath>
#include <iostream>
#include <iterator>
#include <vector>

// assume definition of transform_combinations as above

double power(double x, double y)
{
    // this proxy function is necessary to disambiguate 
    // the call to overloaded std::pow()
    return std::pow(x, y);
}

int main()
{
    std::vector<double> v1;
    v1.push_back(1); v1.push_back(10);
    std::vector<double> v2;
    v2.push_back(0), v2.push_back(1), v2.push_back(2);
    std::vector<double> powers(v1.size()*v2.size());
    transform_combinations(v1.begin(), v1.end(), v2.begin(), v2.end(), powers.begin(), power);

    std::copy(powers.begin(), powers.end(), std::ostream_iterator<double>(std::cout, "\n"));

    return 0;   
}

Output:

1
1
1
1
10
100

PairwiseIterator

The following header defines a new iterator class, which can be used with standard library algorithms, to iterate over two sequences and generate each possible pair. It acts like an InputIterator, i.e. it is a read-only forward iterator, and yields std::pair where T1 and T2 are the types contained in the first and second sequence. There are also two helper functions to generate iterators using template parameter deduction.