我尝试从VS2015更新到VS2017,以下代码在较新版本中无效。如您所见,定义了一个移动构造函数,它自动删除复制构造函数。
#include <boost/optional.hpp>
#include <vector>
struct Foo {
Foo() {}
Foo(Foo&& other) {}
};
int main() {
std::vector<boost::optional<Foo>> foos;
foos.resize(42);
return 0;
}
编译错误是
1>...\boost\dist\include\boost-1_66\boost\optional\optional.hpp(384): error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
1>...\main.cpp(7): note: compiler has generated 'Foo::Foo' here
1>...\boost\dist\include\boost-1_66\boost\optional\optional.hpp(383): note: while compiling class template member function 'void boost::optional_detail::optional_base<T>::construct(const Foo &)'
1> with
1> [
1> T=Foo
1> ]
1>...\boost\dist\include\boost-1_66\boost\optional\optional.hpp(181): note: see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::construct(const Foo &)' being compiled
1> with
1> [
1> T=Foo
1> ]
1>...\boost\dist\include\boost-1_66\boost\optional\optional.hpp(831): note: see reference to class template instantiation 'boost::optional_detail::optional_base<T>' being compiled
1> with
1> [
1> T=Foo
1> ]
1>...\msvc\14.12.25827\include\vector(1902): note: see reference to class template instantiation 'boost::optional<Foo>' being compiled
1>...\msvc\14.12.25827\include\vector(1901): note: while compiling class template member function 'boost::optional<Foo> *std::vector<boost::optional<Foo>,std::allocator<_Ty>>::_Udefault(boost::optional<Foo> *,const unsigned __int64)'
1> with
1> [
1> _Ty=boost::optional<Foo>
1> ]
1>...\msvc\14.12.25827\include\vector(1528): note: see reference to function template instantiation 'boost::optional<Foo> *std::vector<boost::optional<Foo>,std::allocator<_Ty>>::_Udefault(boost::optional<Foo> *,const unsigned __int64)' being compiled
1> with
1> [
1> _Ty=boost::optional<Foo>
1> ]
1>...\main.cpp(10): note: see reference to class template instantiation 'std::vector<boost::optional<Foo>,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=boost::optional<Foo>
1> ]
1>...\main.cpp(7): note: 'Foo::Foo(const Foo &)': function was implicitly deleted because 'Foo' has a user-defined move constructor
现在有趣的是,当我使用std::optional
而不是boost::optional
时,它会编译。我不确定问题是什么,应该责怪谁:我,boost,microsoft,c ++标准?谁知道发生了什么?
这是一个已知问题吗?它是一个提升中的错误还是正确的,它不起作用?
答案 0 :(得分:1)
这似乎是STL实施的一个问题。
从最新的草案,n4700:
26.2.1一般容器要求 [container.requirements.general]定义DefaultInsertable
和MoveInsertable
,并且还部分说明:
T
CopyInsertable
进入X
意味着除了T
MoveInsertable
进入X
之外,以下表达式格式正确:allocator_traits<A>::construct(m, p, v)
及其评估会导致以下后置条件成立:
v
的值保持不变,相当于*p
。
(在这种情况下,T
为boost::optional<Foo>
,X
为std::vector<T>
。)
显然,T
是DefaultInsertable
和MoveInsertable
,而不是CopyInsertable
。
26.3.11.3 vector
容量 [vector.capacity]部分声明:
void resize(size_type sz);
效果:如果
sz < size()
,则会删除序列中的最后size() - sz
个元素。否则,将sz - size()
默认插入的元素附加到序列中。要求:
T
应为MoveInsertable
且DefaultInsertable
为*this
。备注:如果除了非
CopyInsertable
T
的移动构造函数之外引发异常,则不会产生任何影响。
虽然我没有C ++ 11或C ++ 14的官方副本,但基于工作副本,C ++ 11没有&#34; 备注:&#34 ;段落略有不同&#34; 要求:&#34;段:
要求:
T
CopyInsertable
为*this
。
因此,foos.resize(42)
在C ++ 11中的格式不正确,但它应该在C ++ 14中很好地形成,因为T
为MoveInsertable
的要求和{ {1}}对矢量感到满意。
我已确认@patatahooligan's comment将DefaultInsertable
添加到noexcept
移动构造函数允许代码在Clang和g ++ 7.2.0中编译。但是,除非我误读标准,否则不要求非Foo
CopyInsertable
的移动构造函数为noexcept;事实上,该标准似乎允许非T
CopyInsertable
移动构造函数可能抛出异常,在这种情况下,它不能保证是否存在异常的效果。