#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 回答
我假设您使用的是Clang至7.0版本 . bug report 38325记录了此行为 . 然而,它也提出了为什么你看到的行为并非完全不合理的理由 . 从错误报告中引用Richard Smith:
为了解释它,回想一下lambda表达式引入了一种独特的闭包类型 . 就像你写的那样:
现在,当
tmp
是const时,标识符task2
的"type of the entity named"不是const限定的(成员类型没有cv资格) . 所以你有它 . 尽管task2
在函数调用运算符左侧用作后缀表达式时保留了const限定条件,但在检查decltype(task2)
时可能看不到 . 解决方法是强制task2
被视为正则表达式,不受id-expression的decltype
的特殊规则约束 . 你可以通过添加括号来做到这一点:decltype((task2))
将适用于(task2)
的类型和值类别,即decltype(task1) const&
.remove_reference_t
给我们decltype(task1) const
并且您检查的谓词报告您期望的内容 .