首页 > 解决方案 > 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)'

笔记

问题

是什么导致了错误?VS2008 SP1 有 bug 吗?如果是,有什么解决方法?

标签: c++visual-studio-2008c++03compiler-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>.

...

作为解决方法,您可以:

  1. 给 foo 一个默认构造函数。这将快速交换 wstring 并通用交换 foo。
  2. 给 foo 一个默认构造函数,以及一个可以通过 ADL 获取的 swap() 实现。这将快速交换 wstring 和 foo。
  3. 写你自己的一对。这将禁用“交换”。
  4. 使用vector<pair<shared_ptr<foo>, wstring> >. 这将快速交换shared_ptrand wstring。当然,现在您正在进行更多的动态内存分配,所以这仅在某些情况下是可取的。

请注意,当我们获得移动语义时,这种交换机制将被消除,这将是非常棒的。

一种解决方法

在考虑了解决方法后,我选择了#1:如果检测到 VS2008 SP1,则提供默认构造函数:

struct Foo {
    Foo(...) {...}
#if _MSC_FULL_VER == 150030729 // Visual Studio 2008, SP1
    Foo() {} //<- work-around for VS2008 SP1 bug
#endif
};

推荐阅读