首页 文章

没有匹配函数来调用'const std::__1::packaged_task<void ()>'类型的对象,但是`std :: is_const`返回false

提问于
浏览
0
#include <functional>
#include <future>
#include <iostream>
#include <thread>

template<class Func, class... Args>
void submit(Func&& f, Args&&... args) {
  using returnType = typename std::result_of<Func(Args...)>::type;
  auto task1 = std::packaged_task<returnType()>(std::bind(std::forward<Func>(f), std::forward<Args>(args)...));
  std::cout << std::is_const<decltype(task1)>::value << " task1 const or not" << std::endl;

  auto tmp = [task2=std::move(task1)]() {
    std::cout << std::is_const<decltype(task2)>::value << " const or not" << std::endl;  // print 0, which means non-const
    // task2();  // uncomment this line, compilation will fail
  };
  tmp();

}

int main() {
  submit([&] {
    std::cout << "fooooooooo" << std::endl;
  });
  return 0;
}

我知道错误的含义;我知道制作lambda mutable 会有所帮助,我会测试它,但我想知道 const 来自哪里 . 请注意 std::is_const 返回false,这让我很困惑 .

编辑:抱歉忘了提及编译器 . 我正在使用clang-1000.10.44.2 . 该命令是 clang++ -std=c++14 test.cpp -o test

1 回答

  • 1

    我假设您使用的是Clang至7.0版本 . bug report 38325记录了此行为 . 然而,它也提出了为什么你看到的行为并非完全不合理的理由 . 从错误报告中引用Richard Smith:

    Per [expr.prim.id.unqual] p2,lambda中的'x'或'y'的类型是命名相应捕获的类成员访问表达式的类型 . 这些成员是类型(非const)int,但lambda的* this参数是const限定的

    为了解释它,回想一下lambda表达式引入了一种独特的闭包类型 . 就像你写的那样:

    struct unique {
        decltype(task1) task2;
        void operator()() const { /* Your code */ }
    };
    unique const tmp = unique{std::move(tmp1)};
    

    现在,当 tmp 是const时,标识符 task2 的"type of the entity named"不是const限定的(成员类型没有cv资格) . 所以你有它 . 尽管 task2 在函数调用运算符左侧用作后缀表达式时保留了const限定条件,但在检查 decltype(task2) 时可能看不到 . 解决方法是强制 task2 被视为正则表达式,不受id-expression的 decltype 的特殊规则约束 . 你可以通过添加括号来做到这一点:

    std::is_const<std::remove_reference_t<decltype((task2))>>::value
    

    decltype((task2)) 将适用于 (task2) 的类型和值类别,即 decltype(task1) const& . remove_reference_t 给我们 decltype(task1) const 并且您检查的谓词报告您期望的内容 .

相关问题