c++ - VS2008 SP1:将一对推入向量时没有适当的默认构造函数可用
问题描述
背景
类Foo
具有用户声明的构造函数,因此没有隐式声明的默认构造函数:
struct Foo {
Foo(...) {...}
};
然后将其用于std::vector
如下std::pair
:
std::vector<std::pair<std::string, Foo> >
用法
试图推回向量:
std::vector<std::pair<std::string, Foo> > v;
v.push_back(std::make_pair(std::string("some string"), Foo(...)));
编译错误(VS2008 SP1)
以下错误 C2512:
'Foo' : no appropriate default constructor available
...\Microsoft Visual Studio 9.0\VC\include\utility(43):
while compiling class template member function 'std::pair<_Ty1,_Ty2>::pair(void)'
笔记
std::vector
文档说它应该接受可复制和可复制的对象:T必须满足CopyAssignable和CopyConstructible的要求(C++11 之前)。
该代码可以使用 gcc 和 VS2008 (pre SP1) 编译得很好。
问题
是什么导致了错误?VS2008 SP1 有 bug 吗?如果是,有什么解决方法?
解决方案
TL;博士
这是 VS 2008 SP1 中的一个错误。最简单的解决方法是在检测到 VS 2008 SP1 时提供默认构造函数。
解释
在做了一些研究之后,我发现msdn 论坛上的帖子描述了类似的情况。该线程包含来自 Microsoft 员工的答案,其中提供了清晰的解释。
这是报价(为简洁起见,重点是我的):
感谢您报告此错误...这是在 Visual C++ 2008 功能包中引入的,该功能包已合并到 SP1 中。
_Move_operation_category
我们在此处(以及在元组中)有意使用了 OR 。我们想考虑pair<int, string>
快速交换(确实如此)。不幸的是,我们忘记了 Swaptimization 需要一个默认构造函数,并且该对/元组允许用户定义的类型潜入。(使用类似vector<T>
or的东西shared_ptr<T>
,即使T
没有默认构造函数,向量 orshared_ptr
也有。)显然,这是我的错。这个一致性错误有一线希望:至少这个错误让你知道它
vector<pair<foo, wstring> >
会比vector<wstring>
....
作为解决方法,您可以:
- 给 foo 一个默认构造函数。这将快速交换 wstring 并通用交换 foo。
- 给 foo 一个默认构造函数,以及一个可以通过 ADL 获取的 swap() 实现。这将快速交换 wstring 和 foo。
- 写你自己的一对。这将禁用“交换”。
- 使用
vector<pair<shared_ptr<foo>, wstring> >
. 这将快速交换shared_ptr
andwstring
。当然,现在您正在进行更多的动态内存分配,所以这仅在某些情况下是可取的。请注意,当我们获得移动语义时,这种交换机制将被消除,这将是非常棒的。
一种解决方法
在考虑了解决方法后,我选择了#1:如果检测到 VS2008 SP1,则提供默认构造函数:
struct Foo {
Foo(...) {...}
#if _MSC_FULL_VER == 150030729 // Visual Studio 2008, SP1
Foo() {} //<- work-around for VS2008 SP1 bug
#endif
};
推荐阅读
- apache-spark - 基于另一列长度的一列的 Pyspark 子字符串
- c# - 使用 EF Core 包含子项中的 OrderBy
- java - int x= 1+ +2+ +3+ +4+ +5; 在 JAVA 中返回 15
- sql - 在 MS Access 中的查询表达式中出现语法错误(缺少运算符)
- python - 有没有人有一个工作的 WatchedFileHandler 和 StreamHandler 被配置为使用 Python 的日志记录?
- php - PHP 组/嵌套数组结果
- c - Linux 上的线程程序(Posix 线程)
- javascript - 突出显示/将类添加到活动 div
- angular - 离子4中的点击目标视图
- c++ - OpenCV 无法引用扩展模块