I need a way to decompose the function object returned by std::bind()
to its arguments in a function template.
The code snippet below shows what I'd like to do:
#include <iostream>
#include <functional>
void foo(int x, double y, char z)
{
std::cout << "x = " << x << ", y = " << y << ", z = " << z << '\n';
}
int main()
{
auto f = std::bind(foo, 42, 3.14, 'a');
std::cout << "The first argument is: " << std::get<0>(f) << '\n';
std::cout << "The second argument is: " << std::get<1>(f) << '\n';
std::cout << "The third argument is: " << std::get<2>(f) << '\n';
}
The output should be:
The first argument is: 42
The second argument is: 3.14
The third argument is: a
But it doesn't compile with the error:
test.cpp:12:60: error: no matching function for call to ‘get<0>(std::_Bind<void (*(int, double, char))(int, double, char)>&)’
Why do I need this?
std::generate()
and std::generate_n()
can accept both an engine or a distribution to generate random numbers. When you pass a distribution, a standard way is std::bind
in addition to functors and lambdas:
std::mt19937 R(666);
std::::uniform_int_distribution<int> D(0, 100);
std::vector<int> v(10);
std::generate(v.begin(), v.end(), std::bind(D, std::ref(R));
I've developed a parallel generate()
algorithm that plays fair (i.e. you always get the same sequence if you use the same seed and distribution). I'd like it to have the same interface as std::generate()
but the algorithm requires a call to the discard()
function of the engine, which is unnecessary for the serial algorithm. My idea is to use std::is_bind_expression<T>::value
to see if an engine or a distribution is passed. If it's an engine, call discard()
and if it's a bind expression, first decompose it and then call discard()
on the engine. Lambdas are not going to work here because the algorithm can't access the engine.
If it's not possible with the std::bind
implementation, then I'll implement my version of std::bind
.
If there's a better way to do this, I'll be more than glad to know it.
This is not possible.
std::bind
returns an unspecified type with only the following guaranteed:
result_type
type alias;operator()
.If you need the feature described in your question, you must come up with your own definition of bind
.