Skip to content

Instantly share code, notes, and snippets.

@Redchards
Last active December 15, 2015 16:39
Show Gist options
  • Select an option

  • Save Redchards/ac14ba4b957f5b8cc774 to your computer and use it in GitHub Desktop.

Select an option

Save Redchards/ac14ba4b957f5b8cc774 to your computer and use it in GitHub Desktop.
Apply a function to each arguments abusing C++17 upcoming fold expressions and operator coma (compiling with Clang 3.6 and above)
#include <initializer_list>
// The original version, by Eric Niebler and Sean Parent. Abusing brace initialization to make a liste expansion.
// Would work with any variadic initializable construct, such as array types (T[])
template<class Fn, class ... Args>
constexpr Fn for_each_args(Fn f, Args&& ... args)
{
using expander = std::initializer_list<int>;
return ((void)expander{(f(args), 0)...}, f);
}
// Here is the version I came up with using fold expressions. In fact, this is the same principle, but you do
// no longer need to abuse a variadic initializable type to achieve the same effect. Same code generation also.
template<class Fn, class ... Args>
constexpr Fn for_each_args(Fn f, Args&& ... args)
{
return ((..., f(std::forward<Args>(args))), f);
}
// Sample usage :
class Ostreamer
{
public:
template<class T>
void operator()(T x)
{
std::cout << x << std::endl;
}
};
class BasicStreamable
{};
std::ostream& operator<<(std::ostream& os, BasicStreamable)
{
os << "I'm a streamable !\n";
return os;
}
for_each_args(Ostreamer{}, 1, 9, 18, 5, "Hello", " World !", BasicStreamable{});
// Or, if your compiler supports generic lambda functions, you can get read of the "Ostreamer" proxy
for_each_args([](auto x) {
std::cout << x << std::endl;
}, 1, 9, 18, 5, "Hello", " World !", BasicStreamable{});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment