Skip to content

Instantly share code, notes, and snippets.

@engelmarkus
Created October 29, 2016 00:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save engelmarkus/fc1678adbed1b630584c90219f77eb48 to your computer and use it in GitHub Desktop.
Save engelmarkus/fc1678adbed1b630584c90219f77eb48 to your computer and use it in GitHub Desktop.
std::bind for variadic functions
/*
When using std::bind, all parameters have to be bound either to a value or to a placeholder.
This makes it impossible to use std::bind with variadic functions if you do not know the number
of parameters they take in advance.
This gist shows how to allow binding the first parameters of variadic functions.
The original idea can be found here: http://stackoverflow.com/questions/21192659/variadic-templates-and-stdbind#21193316
*/
#include <experimental/tuple>
#include <functional>
#include <iostream>
#include <utility>
template <int>
struct variadic_placeholder {};
namespace std {
template <int N>
struct is_placeholder<variadic_placeholder<N>>
: integral_constant<int, N + 1>
{
};
}
template <typename Ret, typename Class, typename... Args, size_t... Is, typename... Args2>
auto bind(std::index_sequence<Is...>, Ret (Class::*fptr)(Args...), Args2&&... args) {
return std::bind(fptr, std::forward<Args2>(args)..., variadic_placeholder<Is>{}...);
}
template <typename Ret, typename Class, typename... Args, typename... Args2>
auto bind(Ret (Class::*fptr)(Args...), Args2&&... args) {
return bind(std::make_index_sequence<sizeof...(Args) - sizeof...(Args2) + 1>{}, fptr, std::forward<Args2>(args)...);
}
template <typename... Ts>
struct Counter {
auto numTs(Ts...) {
return sizeof...(Ts);
}
};
int main() {
Counter<int, int, int> ctr;
auto f = bind(&decltype(ctr)::numTs, &ctr);
auto params = std::make_tuple(1, 2, 3);
std::cout << std::experimental::apply(f, params) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment