Category Archives: c++

C++0x lambdas in GCC 4.5

Lambdas are coming in GCC 4.5. With this I’ve rid myself of the clamp hack. You can start using lambdas today by just grabbing a GCC snapshot:

svn co -q svn://gcc.gnu.org/svn/gcc/trunk
sudo aptitude build-dep gcc-4.4 # get prereqs
./configure --program-suffix=-4.5 --disable-libgcj \
    --enable-languages=c++
make
sudo make install
# test it out
echo 'int main() { []{}; return 0; }' > /tmp/nop.cc
g++-4.5 -std=gnu++0x -o /tmp/nop{,.cc}

Here’s a simple program from my C++ sandbox showing off just a few of C++0x’s slew of new features:

#define _GLIBCXX_USE_NANOSLEEP
#include <functional>
#include <iostream>
#include <string>
#include <thread>
#include <vector>

using namespace std;
int main() {
  // strongly typed enums
  // can specify underlying type
  enum class msg_type : uint8_t { hello, world };
  // initializer lists for easy init
  // no more `>>` misparsing
  const vector<pair<int, string>> xs =
    {{1, "hello"}, {3, "world"}};
  // standard classes for concurrency
  vector<thread> ts;
  // type inference with repurposed `auto`
  // no need for `vector<string>::const_iterator`
  for (auto x = xs.begin(); x != xs.end(); ++x) {
    // new function class
    // could also use `auto` here
    // here's a lambda that captures x by value
    function<void()> f = [=]{
      // new chrono class
      std::this_thread::sleep_for(
        chrono::seconds(x->first));
      cout << x->second << endl;
    };
    ts.push_back(thread(f));
  }
  for (auto t = ts.begin(); t != ts.end(); ++t) {
    t->join();
  }
  return 0;
}

Compile it with:

g++-4.5 -std=gnu++0x -pthread -o c++0x{,.cc}

Other features are coming down the pipe as well. Wikipedia has good high-level overviews of these and more.

Lazy C++

Ever been fed up with having to separate declaration from definition in C++? Annoyed by the need to forward-declare your types/variables/functions, or at least write them in dependency-dictated order? Sick of keeping header files in sync with the source? With Lazy C++, you can leave your frustrations behind! Simply plop both your declarations and your definitions into a single file, and Lazy C++ will automagically tease the code apart into a standard header file and source file. The website and documentation provide self-explanatory examples:

For example, given the following code:

// A.lzz
class A
{
public:
  inline void f (int i) { ... }
  void g (int j = 0) { ... }
};
bool operator == (A const & a1, A const & a2) { ... }

Lzz will generate a header file:

// A.h
#ifndef LZZ_A_h
#define LZZ_A_h

class A
{
public:
  void f (int i);
  void g (int j = 0);
};
inline void A::f (int i) { ... }
bool operator == (A const & a1, A const & a2);
#endif

And a source file:

// A.cpp
#include "A.h"

void A::g (int j) { ... }
bool operator == (A const & a1, A const & a2) { ... }

Lazy C++ is a simple idea, but its implementation is at best tedious, requiring the parsing of a non-trivial subset of C++. It gets things right, though. It knows, for instance, to place inlines and templates into headers, to move method and function bodies out of the header when possible, and to restrict static declarations to the source. It also has escape hatches to let you directly place code into the header or source (this is particularly useful when using macros like unit test definitions). It tries to leave function bodies unparsed, which provides flexibility in allowing for C++ language extensions (such as clamp’s lambda expressions).

D—whose primary implementation recently had its source released (albeit not fully free nor open-source)—takes things a step further:

Features To Drop [from C/C++]

  • Forward declarations. C compilers semantically only know about what has lexically preceded the current state. C++ extends this a little, in that class members can rely on forward referenced class members. D takes this to its logical conclusion, forward declarations are no longer necessary at the module level. Functions can be defined in a natural order rather than the typical inside-out order commonly used in C programs to avoid writing forward declarations.
  • Include files. A major cause of slow compiles as each compilation unit must reparse enormous quantities of header files. Include files should be done as importing a symbol table.

While I’m on it: D is a pretty interesting language to follow, for a number of reasons. It has the feel of being a sensible evolution and clean-up of C++, and it’s the only thing out there besides C/C++ that one can pick up and start using right away as a systems programming language with (accessible) manual memory management. D is actually being used/gathering libraries within a growing community. Also, the language has some pretty good people working on its design, including C++ experts like Andrei Alexandrescu.

The C++ Lambda Preprocessor

Tired of waiting around for anonymous closures to arrive in C++0x (or at least in GCC)? Boost.Lambda and other hacks leaving you pining for something with free variable capture? Get them today with the amazing C++ Lambda Preprocessor (“clamp”)!

Here’s a little demo illustrating the use of lambdas with threads—something which may be more interesting to systems programmers than the simple accumulator examples on the clamp homepage.

#include <boost/thread.hpp>
#include <iostream>

using namespace boost;
using namespace std;
#include "lambda_impl.clamp_h"

enum { n = 3 };
int main() {
  const string msgs[n] = {"first", "second", "third"};
  mutex m;
  for (int i = 0; i < n; ++i) {
    boost::thread(lambda() {
      mutex::scoped_lock l(__ref(m));
      cout << "message from thread " << __ctx(i)
           << ": " << __ref(msgs[i]) << endl;
    });
  }
  return 0;
}

// clamp < clamp2.cc.clamp | sed '1d' > clamp2.cc
// g++     clamp2.cc  -lboost_thread-gcc43-mt -o clamp2
// ./clamp2

There are a few annoyances with clamp:

  • All free variables must be explicitly captured with __ref() or __ctx(). This is because clamp doesn’t try to actually parse your C++ (understandably). (Not parsing the C++ also makes it more flexible, accommodating various language extensions.) Contrast this with C++0x, where you can use short-hand notations like [&], which captures all free variables by reference (perhaps the most common case).
  • You will most likely need to muck with the output. clamp generates a number of header files that form the first #include in your source file. However, if you ever refer to global types/variables/functions, you will need to reorder things, add forward declarations, separate the generated header contents into declarations and definitions, etc. This is made nearly trivial, however, if you also use Lazy C++, which I’ll cover next time.

Despite these minor quibbles, clamp is simple and effective. The generated code is straightforward—pretty much exactly what you would expect to write yourself by hand.

unique_ptr and nullptr for C++03

(I’ve been using C++ a bunch lately, so the next several posts will probably be pretty C++-centric.)

unique_ptr is the future. And the future is now! Start using unique_ptr today with this little gem, a C++03-compatible implementation. Of course, you get fancy new C++0x move semantics, pioneered by auto_ptr, but now safer, saner, more widely usable (e.g. in containers), etc. unique_ptr also supports arrays without a separate unique_array class: unique_ptr<T[]> is template-specialized. (I won’t spend this post describing unique_ptr; the provided links already do a much better job at that.)

Some more opinion from the C++03-compatible unique_ptr page:

A const unique_ptr may be considered a better scoped_ptr than even boost::scoped_ptr. The only way to transfer ownership away from a const unique_ptr is by using const_cast. Unlike scoped_ptr, you can’t even swap const unique_ptr’s. The overhead is the same (if using the default_delete or an empty custom deleter – sizeof(unique_ptr<T>) == sizeof(scoped_ptr<T>)). And custom deleters are not even a possibility with scoped_ptr.

(Note BTW that boost::interprocess::unique_ptr is not the same as the C++0x unique_ptr.)

In general, you can already achieve move semantics without rvalue-references, just by using const_cast (or mutable). This is indeed how this unique_ptr implementation works. The core idea illustrated:

template<typename T>
class moveable_ptr {
  T *p;

  // Disable copying from lvalues.
  moveable_ptr(moveable_ptr<T> &o) : p(nullptr) {}

public:
  moveable_ptr(T *p) : p(p) {}

  // In C++0x:
  // moveable_ptr(moveable_ptr<T> &&o) : p(o.p) {
  //   o.p = nullptr;
  // }

  // In C++03, settle with:
  moveable_ptr(const moveable_ptr<T> &o) : p(o.p) {
    const_cast<T*>(o.p) = nullptr;
  }

  ~moveable_ptr() { if (p) delete p; }
  T *get() const { return p; }
  ...
};

Notice above that I use nullptr instead of 0 or NULL—that’s another C++0x feature you can begin using right away, and without any hackery at all.

These goodies are all collected in my growing C++ Commons library.

C++ copy elimination

What does the following C++ program print?

class A {
  public:
    A()           { cout << "A()" << endl; }
    A(const A &a) { cout << "A(A)" << endl; }
};
A g() { A a; return a; }
int main() { A a(g()); }

The answer: it depends on what compiler you’re using. You might expect:

A()
A(A)

With most full-featured C++ compilers, however (including GCC), the constructor is called once:

A()

This turns out to be an “optimization” that is explicitly mention in the language standard. It’s one for which C++ implementations are allowed to forgo the straightforward semantics. From section 12.8.14 of the C++98 standard:

Whenever a temporary class object is copied using a copy constructor, and this object and the copy have the same cv-unqualified type, an implementation is permitted to treat the original and the copy as two different ways of referring to the same object and not perform a copy at all, even if the class copy constructor or destructor have side effects. For a function with a class return type, if the expression in the return statement is the name of a local object, and the cv-unqualified type of the local object is the same as the function return type, an implementation is permitted to omit creating the temporary object to hold the function return value, even if the class copy constructor or destructor has side effects. In these cases, the object is destroyed at the later of times when the original and the copy would have been destroyed without the optimization.

This is described more elsewhere in the spec, with examples (e.g. 12.2.2). The MSDN Library also has an article on named return value optimization.

In the end, it’s nice to be able to write more expressive/higher-level-looking code without worrying about unnecessary copies being made. However, you may have to pay attention to certain cases where your ctors/dtors have side effects you’re relying on, and it may be subtle to figure out when copies are or aren’t actually being eliminated.

More experimentation with this feature can be found in this source file, part of my ever-growing sandbox of toy code.

Thanks to SIPB and ##c++ for the discussion.