VariadicTemplateAlgorithms icon indicating copy to clipboard operation
VariadicTemplateAlgorithms copied to clipboard

A C++14 library to make it easier to work with parameter packs

Variadic Template Algorithms

Build Status

Working with parameter packs in C++ can be difficult. Getting a reference to the last argument of a parameter pack or reversing the order of arguments to a function is much harder than it should be. VTA is a header-only C++14 library to make this easier.

Grabbing the nth parameter is very simple with vta::head, vta::at, and vta::last:

auto i = vta::head(1, "hello"s, 3.14, '!');   // i is an int with value 1
auto c = vta::last(1, "hello"s, 3.14, '!');   // l is a char with value '!'
auto s = vta::at<1>(1, "hello"s, 3.14, '!');  // s is a std::string with value "hello"

// vta::at can take negative values to index backward from the end
auto d = vta::at<-2>(1, "hello"s, 3.14, '!'); // d is a double with value 3.14

There are many functions which return functors that apply a function across any number of arguments. Writing a max function is simple when you can fold across any number of parameters,

template <typename... Args>
auto max(Args... args) {
	// Check that all of the arguments are of the same type
	static_assert(vta::are_same<typename std::decay<Args...>::type>::value,
	  "Arguments to max must have the same type");

	// Create a max lambda that can operate on any type
	// (note this line is not needed if the VTA_FN_TO_FUNCTOR macro is used)
	auto max = [](auto const& l, auto const& r){ return std::max(l, r); };

	// Perform a left fold across the arguments, returning the maximum
	return vta::foldl(max)(args...);
}

Reversing arguments and forwarding them on is also easy,

// Prints an argument
auto printer = [](auto const& x){ std::cout << x; };

// Prints all arguments in order
template <typename... Args>
void print(Args... args) {
	// vta::map applies a function to each argument in order
	vta::map(printer)(args...);
}

// Prints all arguments in reverse order
template <typename... Args>
void reverse_print(Args... args) {
	// vta::forward_after forwards the arguments to a function after a transformation
	vta::forward_after<vta::reverse>(vta::map(printer))(args...);
}

The vta::forward_after function can perform many other transformations such as swapping arguments or shifting all arguments to the left. The full list of transformation can be found in the api reference.