Home > Back-end >  Issue with capturing of a variadic pack inside of lambda in MSVC19
Issue with capturing of a variadic pack inside of lambda in MSVC19

Time:01-30

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:

  1. this is valid C 20, right?
  2. is there a work around for MSVC such that I can use these kind of constructs? (i.e. making it SFINAE-friendly).

CodePudding user response:

  1. this is valid C 20, right?

Yes, lambdas can be constrained by requires clauses in C 20, so it's well-formed.

  1. 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 clauses. 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...);
    };
}

Demo.

It is worth noting that P2387 also introduced std::bind_back to support pipe operator for user-defined scope adapters.

  •  Tags:  
  • Related