C++11 Lambda Expression Overloading

I recently read about a neat trick regarding overloading of lambda expressions in C++ in a blog post by Dave Abrahams here. This technique was originally described by Mathias Gaunard. I want to do a short post about it here so I don't forget it.

In C++11, it is possible to overload lambda expressions by creating a helper function object class that inherits from the function objects the compiler generates for the lambda expressions and then pulling in the lambda expressions' operator() via using declarations.

Simple Example

Here's a simple console application that demonstrates this for two lambda expressions:

#include <iostream>

template <class F1, class F2>
struct overload_set : F1, F2
{
	overload_set(F1 f1, F2f2)
		: F1(f1), F2(f2)
	{}

	using F1::operator();
	using F2::operator();
};

template <class F1, class F2>
overload_set<F1, F2> overload(F1 f1, F2 f2)
{
	return overload_set<F1, F2>(f1, f2);
}

int main(int argc, const char* argv[])
{
	auto f = overload
		(
			[]() { return 1; },
			[](int x) { return x + 1; }
		);

	int x = f();
	int y = f(2);

	std::cout << "x = " << x << ", y = " << y << std::endl;

	return 0;
}

The overload function in this example returns a function object called overload_set that inherits from the two function objects created by the compiler for the two lambda expressions passed to it. Note that you don't necessarily have to use lambda expressions. Any function object class that exposes an operator() can be used.

The two operator() are then pulled into the overload_set class via a using declaration. So client code now sees a function object class that provides two operator(), in this case, one that has no arguments and one that has an integer argument. When calling through the function object regular function overloading comes into play and the compiler chooses the correct function to call depending on the supplied arguments.

Variadic Template Implementation

Here's a more general implementation of the technique described above using variadic templates. If you're not yet familiar with C++11 variadic templates, the Wikipedia page on the subject is pretty good.

template <class... Fs> struct overload_set;

template <class F1, class... Fs>
struct overload_set<F1, Fs...> : F1, overload_set<Fs...>::type
{
	typedef overload_set type;

	overload_set(F1 head, Fs... tail)
		: F1(head), overload_set<Fs...>::type(tail...)
	{}

	using F1::operator();
	using overload_set<Fs...>::type::operator();
};

template <class F>
struct overload_set<F> : F
{
	typedef F type;
	using F::operator();
};

template <class... Fs>
typename overload_set<Fs...>::type overload(Fs... x)
{
	return overload_set<Fs...>(x...);
}

This is quite a neat trick, even though admittedly it probably won't be useful very often. It might come in handy for certain generic algorithms, for example to implement compile-time double dispatch.

One thought on “C++11 Lambda Expression Overloading

  1. Pingback: C++11 "overloaded lambda" with variadic template and variable capture - BlogoSfera

Leave a Reply

Your email address will not be published. Required fields are marked *