Reputation: 676
I am using Clang 14.0.0 and C++20. My goal is to write a general function in order to use std::lerp
on a set of elements. So I came up with this:
template <typename InputIterator, typename OutputIterator>
constexpr OutputIterator
lerp_element(InputIterator first, InputIterator last, OutputIterator result,
std::iter_value_t<InputIterator> const& a,
std::iter_value_t<InputIterator> const& b)
{
return std::transform(first, last, result, [&a, &b] (auto const &t) { return std::lerp(a, b, t); });
}
This works well, however - in an attempt to find a better/alternative way - I thought that maybe a version with std::bind
could be more concise and elegant:
template <typename InputIterator, typename OutputIterator>
constexpr
OutputIterator
lerp_element(InputIterator first, InputIterator last, OutputIterator result,
std::iter_value_t<InputIterator> const& a,
std::iter_value_t<InputIterator> const& b)
{
return std::transform(first, last, result, std::bind(std::lerp(a, b, std::placeholders::_3)));
}
Lastly I found that std::bind_front
allows me to be even less verbose:
template <typename InputIterator, typename OutputIterator>
constexpr
OutputIterator
lerp_element(InputIterator first, InputIterator last, OutputIterator result,
std::iter_value_t<InputIterator> const& a,
std::iter_value_t<InputIterator> const& b)
{
return std::transform(first, last, result, std::bind_front(std::lerp(a, b)));
}
The problem is when I try to compile the two latter versions (the ones that use std::bind
and std::bind_front
), Clang throws this error message at me:
Here is the calling code:
int main() {
std::vector<double> v = { 0.11, 0.53, 0.32, 0.29, 0.77, 0.45, 0.96, 0.0, 1.0 };
std::vector<double> results;
lerp_element(std::begin(v), std::end(v), std::back_inserter(results), 10.0, 20.0);
for (auto x : results) { std::cout << x << ' '; }
return 0;
}
Since I have the version with the lambda working, it seems the issue must be in the way I am using std::bind
. I have been reading everything I could find online on how to properly use std::bind
and std::placeholders
, but obviously I must not be getting it.
I understand the problem has to do with std::lerp
not receiving consistent argument types in order to resolve the overload, so:
std::bind
/std::bind_front
versions to make it compile and work as expected?Upvotes: 0
Views: 136
Reputation: 51886
The function argument to std::bind
or std::bind_front
should not be invoked, but rather the function itself is passed as the first argument:
using T = std::iter_value_t<InputIterator>;
using F = T (*)(T, T, T) noexcept;
return std::transform(first, last, result,
std::bind_front<F>(std::lerp, a, b));
Upvotes: 3