c++ - 为什么转换 std::packaged_task 的构造函数显式?
问题描述
为什么转换构造函数是std::packaged_task
explicit
,而同一个构造函数std::function
不是?我找不到任何理由。
例如,这在将 lambda 作为参数传递给以 a packaged_task
(或对它的引用)作为参数的函数时强制转换:
void f1(std::function<void()>);
std::future<void> f2(std::packaged_task<void()>);
int main()
{
f1( []{ } ); // ok
auto fut = f2( []{ } ); // error
auto fut = f2( (std::packaged_task<void()>) []{ } ); // ok
fut.wait();
}
解决方案
考虑以下示例。让我们创建一个模板类来模拟具有非显式模板转换构造函数的类。
#include <iostream>
// Hypothetical overloaded constructor
template <class T>
struct Foo {
template <class F>
Foo(F&& f ) { std::cout << "Initialization of Foo \n"; }
Foo(const Foo& ) { std::cout << "Copy of Foo\n"; }
Foo(Foo&& ) { std::cout << "Move of Foo\n"; }
};
void bar( Foo<int> f ) {}
int main()
{
int a = 0;
std::cout << "1st case\n";
bar(a);
std::cout << "2nd case\n";
bar(Foo<int>(a)); // incorrect behaviour
}
输出将是
1st case
Initialization of Foo
2nd case
Initialization of Foo
在这两种情况下,模板都会劫持控制权!在这种情况下,您实际上不能使用复制\移动构造函数。避免它的最简单方法是显式转换。
#include <iostream>
// Analog of standard's constructor idiom
template <class T>
struct Foo2 {
template <class F>
explicit Foo2(F&& f ) { std::cout << "Initialization of Foo2 \n"; }
Foo2(const Foo2& ) { std::cout << "Copy of Foo2\n"; }
Foo2(Foo2&& ) { std::cout << "Move of Foo2\n"; }
};
void bar2( Foo2<int> f ) {}
int main()
{
int a = 0;
Foo2<int> f{a};
std::cout << "\nProper case 1\n";
// bar2(a); - can't do that
bar2(Foo2<int>(a));
std::cout << "Proper case 2\n";
bar2(f);
return 0;
}
输出:
Initialization of Foo2
Proper case 1
Initialization of Foo2
Proper case 2
Copy of Foo2
std::function
是可复制的,同时std::packaged_task
必须定义自定义移动构造函数和删除复制构造函数。
在尝试传递std::function
时,在这两种情况下都不会发生任何 BAD,复制和移动构造函数很可能对函数指针或对可调用对象的引用进行操作,std::function
旨在对任何兼容的可调用对象(包括其自身)进行操作。
如果您尝试这样做 std::packaged_task
,则转换构造函数可能会做错事或可能无法编译,因为它无法使用自己的类的实例。一个看起来像复制的语句(但实际上是.. 移动?赋值?)是可能的。
推荐阅读
- azure - 无法在 Azure 批处理 VM 中获取环境变量
- sql - XML 文档到 SQL Server 查询
- sonarqube - sonarQube 无法生成覆盖文件
- google-chrome - Google MyMaps 不允许我延长线
- python - 使用 Dask 并行运行 PyBaMM 电池模拟
- python - 类型错误:change() 缺少 2 个必需的位置参数:“B1”和“B2”
- javascript - 如何在我的网站(HTML、CSS 和 JavaScript)中使用来自 python 文件的数据?
- javascript - 如何在隐藏 html/javascript 的情况下将我的计算代码上传到我的网站?
- c++ - 尝试按下按钮并以 2Hz 切换 LED 闪烁,直到我再次按下按钮
- c++ - 无法覆盖方法 C++