Released some time ago new C++11 standard introduced lambda functions - long anticipated and exciting feature. On the other hand, boost::variant has been around for awhile and is used successfully in many projects. The recommended and type-safe way of applying type-specific logic to values of variant types is using visitor pattern. However, a visitor is a functor, which until now should have been defined separately, in a class of its own. It would be nice if we could use lambda functions to achieve the same functionality. Thanks to some clever folks on StackTrace, we can do exactly that:
/// Define helper classes and function
template <typename ReturnT, typename... Lambdas>
struct lambda_visitor;
template <typename ReturnT, typename L1, typename... Lambdas>
struct lambda_visitor< ReturnT, L1 , Lambdas...> : public L1, public lambda_visitor<ReturnT, Lambdas...>
{
using L1::operator();
using lambda_visitor< ReturnT , Lambdas...>::operator();
lambda_visitor(L1 l1, Lambdas... lambdas)
: L1(l1), lambda_visitor< ReturnT , Lambdas...> (lambdas...)
{}
};
template <typename ReturnT, typename L1>
struct lambda_visitor<ReturnT, L1> : public L1, public boost::static_visitor<ReturnT>
{
using L1::operator();
lambda_visitor(L1 l1)
: L1(l1), boost::static_visitor<ReturnT>()
{}
};
template <typename ReturnT>
struct lambda_visitor<ReturnT> : public boost::static_visitor<ReturnT>
{
lambda_visitor() : boost::static_visitor<ReturnT>() {}
};
template <typename ReturnT, typename... Lambdas>
lambda_visitor<ReturnT, Lambdas...> make_lambda_visitor(Lambdas... lambdas)
{
return { lambdas... };
}
/// Now we can use lambdas directly
auto val = boost::variant<std::string, int>("Test");
auto visitor = make_lambda_visitor<void>(
[](const std::string & str) { std::cout << str; },
[](const int& sec) { std::cout << sec; });
boost::apply_visitor(visitor, val);
Relevant source .