#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
答案 0 :(得分:1)
我将假设您使用的是7.0版以上的Clang。 bug report 38325记录了此行为。但是,它也提供了为什么您看到的行为并非完全不合理的理由。引用错误报告中的Richard Smith:
每个[expr.prim.id.unqual] p2,lambda中的'x'或'y'类型 是命名成员的类成员访问表达式的类型 相应的捕获。这些成员是(non-const)int类型的,但是 lambda的*此参数是const限定的
要解释这一点,请记住,lambda表达式引入了唯一的闭包类型。就像你写的一样:
struct unique {
decltype(task1) task2;
void operator()() const { /* Your code */ }
};
unique const tmp = unique{std::move(tmp1)};
现在,虽然tmp
是const ,但标识符task2
的“命名实体的类型”不具有const限定(成员类型没有cv限定) 。所以你有它。即使task2
用作函数调用操作符左侧的 postfix-expression 时,它会保留const限定符,但在检查decltype(task2)
时,您可能看不到。解决方法是强制将task2
视为正则表达式,而不要遵守decltype
对于id表达式的特殊规则。您可以通过添加括号来做到这一点:
std::is_const<std::remove_reference_t<decltype((task2))>>::value
decltype((task2))
适用于(task2)
的类型和值类别,即decltype(task1) const&
。 remove_reference_t
给了我们decltype(task1) const
,您检查的谓词报告了您的期望。