无法通过 std::ref() 使用 auto& 参数调用 std::invoke()

Cannot call std::invoke() with auto& parameter via std::ref()

本文关键字:std 参数 调用 invoke auto 使用 ref      更新时间:2023-10-16

我正在尝试创建一个 Invoker对象,该对象同时存储函数和一组函数的参数 - ast by value(用于螺纹(。 Invoker::operator()()将使用复制的参数调用存储的函数。

到目前为止,一切都很好,直到人们尝试使用auto&通过CC_3传递参数。具体而言,此代码应起作用,而是与给定的错误消息没有编译:

int var = 0;
Invoker{
    [](auto& r) {
        printf("%dn", r);
    }, std::ref(var)
}();

我希望它的工作原理类似于std::thread在此示例中的工作方式。错误消息是:

test.cpp:65:14: error: no matching function for call to ‘invoke(std::__tuple_element_t<0, std::tuple<main()::<lambda(auto:1&)>, std::reference_wrapper<int> > >, std::__tuple_element_t<1, std::tuple<main()::<lambda(auto:1&)>, std::reference_wrapper<int> > >)’
   std::invoke(std::get<Indicies>(std::move(args))...);
   ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我当前的Invoker类:

template<typename... Args>
struct Invoker {
    std::tuple<std::decay_t<Args>...> args;
    explicit Invoker(Args... args)
        : args(std::forward<Args>(args)...)
    { }
    template<size_t... Indices>
    void _Invoke(std::index_sequence<Indices...>) {
        std::invoke(std::get<Indices>(std::move(args))...);
    }
    void operator()() {
        _Invoke(std::make_index_sequence<std::tuple_size_v<decltype(args)>>{});
    }
};
/* Invoker deduction guide (perfectly forward any parameters with full type!) */
template<typename Function, typename... Args>
Invoker(Function&&, Args&&...) -> Invoker<Function&&, Args&&...>;

有关此问题的在线版本,请参见此处。错误消息表明,当应为int&时,推论的auto&类型为std::reference_wrapper<int>&。不幸的是,我无法提出解决这个问题的解决方案。

编辑:

如评论所示,表达式

int var = 5;
std::thread{ [](auto& r) { printf("%dn", r); }, std::ref(var) };

仅使用gcc >= 7.1.0编译。我很高兴看到有关此主题的详细说明,特别是如果C 标准这是正确的行为。

INVOKE通常不会取消包装reference_wrapper参数;它们被用作IS(一个例外,此处无关:如果将reference_wrapper作为第一个参数的成员调用指针,则该参数是未包装的(。因此,invoke([](auto&){}, std::ref(var));将尝试使用RVALUE reference_wrapper调用Lambda,该lambda试图将RVALUE绑定到LVALUE参考。

std::thread观察到的行为是已固定的LIBSTDC 错误。简而言之,libstdc 的 std::thread将提供的参数存储在tuple中,该参数(错误地(用make_tuple构建(它取消了reference_wrapper s(。