I'm trying to write a SFINAE-friendly bind_back
function, similar to C++20's std::bind_front
. However, it seems that MSVC is having some issues with the code.
I managed to minimize the issue to the following code fragment:
auto bind_back(auto f, auto ...back_args) {
return [=](auto ...front_args)
requires requires { f(front_args..., back_args...); } {
return f(front_args..., back_args...);
};
}
int main() {
auto h = bind_back([]{});
h();
}
https://godbolt.org/z/3bc8GaqTv
While compiling this fragment, I get the following error:
<source>(10): error C2672: 'operator __surrogate_func': no matching overloaded function found
<source>(10): error C2893: Failed to specialize function template 'decltype(auto) bind_back::<lambda_1>::operator ()(_T1...) const'
<source>(5): note: see declaration of 'bind_back::<lambda_1>::operator ()'
<source>(10): note: With the following template arguments:
<source>(10): note: '_T1={}'
It seems that both Clang and GCC have no problems compiling this code.
My questions are:
- this is valid C++20, right?
Yes, lambdas can be constrained by requires clause in C++20, so it's well-formed.
- is there a work around for MSVC such that I can use these kind of constructs? (i.e. making it SFINAE-friendly).
MSVC seems to have some issues with handling requires clause. Instead, you can use std::invocable
:
#include <concepts>
template<class F, class... BoundArgs>
auto bind_back(F f, BoundArgs... bound_args) {
return [=]<class... CallArgs>(CallArgs... call_args)
requires std::invocable<F&, CallArgs&..., BoundArgs&...> {
return f(call_args..., bound_args...);
};
}
It is worth noting that P2387 also introduced std::bind_back
to support pipe operator for user-defined scope adapters.