Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法使用自动调用std::invoke();通过std::ref()的参数_C++_C++11_Lambda_C++17 - Fatal编程技术网

C++ 无法使用自动调用std::invoke();通过std::ref()的参数

C++ 无法使用自动调用std::invoke();通过std::ref()的参数,c++,c++11,lambda,c++17,C++,C++11,Lambda,C++17,我正在尝试创建一个调用程序对象,该对象存储一个functor和该functor的一组参数-全部按值(用于线程)。 Invoker::operator()()将使用复制的参数调用存储的functor 到目前为止,一切正常,直到人们尝试使用std::ref(variable)通过auto&传递参数。具体来说,此代码应该可以工作,但它不会使用给定的错误消息进行编译: int var = 0; Invoker{ [](auto& r) { printf("%d\n", r

我正在尝试创建一个
调用程序
对象,该对象存储一个functor和该functor的一组参数-全部按值(用于线程)。
Invoker::operator()()
将使用复制的参数调用存储的functor

到目前为止,一切正常,直到人们尝试使用
std::ref(variable)
通过
auto&
传递参数。具体来说,此代码应该可以工作,但它不会使用给定的错误消息进行编译:

int var = 0;
Invoker{
    [](auto& r) {
        printf("%d\n", r);
    }, std::ref(var)
}();
我希望它的工作方式类似于
std::thread
在本例中的工作方式。 错误消息是:

获取此问题的联机版本。错误消息表明,
auto&
的推断类型是
std::reference\u wrapper&
,而它应该是
int&
。不幸的是,我不能想出解决这个问题的办法

编辑: 正如评论所显示的,这个表达

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

仅编译为
gcc>=7.1.0
。我希望看到这个主题的详细阐述,特别是如果这是C++行为的正确行为。

<代码>调用> <代码>一般不拆开<代码>参考文献包装> <代码>参数;它们按原样使用(有一个例外与此无关:如果调用指向成员的指针,并将
引用_包装器
作为第一个参数,则该参数将被展开)。因此,
invoke([](auto&){},std::ref(var))
将尝试使用右值
引用\u包装
调用lambda,这对于尝试将右值绑定到左值引用来说是格式错误的


使用
std::thread
观察到的行为是已修复的。简而言之,libstdc++的
std::thread
将提供的参数存储在
元组中,该元组是(错误地)用
make\u tuple
构造的(它打开
reference\u wrapper
s)。

INVOKE
通常不打开
reference\u wrapper
参数;它们按原样使用(有一个例外与此无关:如果调用指向成员的指针,并将
引用_包装器
作为第一个参数,则该参数将被展开)。因此,
invoke([](auto&){},std::ref(var))
将尝试使用右值
引用\u包装
调用lambda,这对于尝试将右值绑定到左值引用来说是格式错误的


使用
std::thread
观察到的行为是已修复的。简而言之,libstdc++的
std::thread
将提供的参数存储在一个
元组中,该元组是(错误地)用
make\u tuple
构造的(打开
reference\u wrapper

auto
的推断使用相同的规则进行模板参数推断,这不允许隐式转换。问题可通过
int n=5再现;自动&r=ref(n)。由于
ref(n)
是一个右值,因此它不能绑定到左值引用。@0x499602D2不过,当使用
std::thread
时,它仍能正常工作。我想复制一下behaviour@nyronium否,
std::thread([](auto&ref){},std::ref(var))从不编译。@如果你错了。请参见。
auto
的报告为推断使用相同的模板参数推断规则,这不允许隐式转换。问题可通过
int n=5再现;自动&r=ref(n)。由于
ref(n)
是一个右值,因此它不能绑定到左值引用。@0x499602D2不过,当使用
std::thread
时,它仍能正常工作。我想复制一下behaviour@nyronium否,
std::thread([](auto&ref){},std::ref(var))从不编译。@如果你错了。见。报告为
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 var = 5;
std::thread{ [](auto& r) { printf("%d\n", r); }, std::ref(var) };