Rec*_*ker 4 c++ c++11 visual-studio-2015
以下代码在clang-3.8和gcc 4.9.3上编译得很好.
#include <vector>
#include <algorithm>
#include <iterator>
class foo
{
};
class MyVec {
public:
MyVec() {}
};
class MyInsert :
public std::iterator<std::output_iterator_tag, void, void, void, void>
{
protected :
MyVec &fV;
public :
explicit MyInsert (MyVec &v) : fV(v) {}
MyInsert & operator= (void *value)
{
return *this;
}
MyInsert & operator* () { return *this; }
MyInsert & operator++ () { return *this; }
MyInsert & operator++(int) { return *this; }
};
class test
{
public:
void method()
{
MyVec retv;
std::vector<const foo*> foovec;
std::transform(foovec.begin(), foovec.end(),MyInsert(retv),[](const foo*)->void* { return nullptr;});
}
};
int main(){
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,在VS 2015 Update 3上编译时,它会失败,并显示以下错误消息.
c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(458): error C2280: 'MyInsert &MyInsert::operator =(const MyInsert &)': attempting to reference a deleted function
test\mytests\main.cpp(33): note: compiler has generated 'MyInsert::operator =' here
c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(926): note: see reference to function template instantiation '_Iter &std::_Rechecked<_OutIt,_OutIt>(_Iter &,_UIter)' being compiled
with
[
_Iter=MyInsert,
_OutIt=MyInsert,
_UIter=MyInsert
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(950): note: see reference to function template instantiation '_OutIt std::_Transform_no_deprecate1<const foo**,_OutIt,_Fn1>(_InIt,_InIt,
_OutIt,_Fn1 &,std::input_iterator_tag,std::_Any_tag)' being compiled
with
[
_OutIt=MyInsert,
_Fn1=test::method::<lambda_45e8626339fc29aadca2bf2dd3420511>,
_InIt=const foo **
]
c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(960): note: see reference to function template instantiation '_OutIt std::_Transform_no_deprecate<_InIt,_OutIt,_Fn1>(_InIt,_InIt,_OutIt,
_Fn1 &)' being compiled
with
[
_OutIt=MyInsert,
_InIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<const foo *>>>,
_Fn1=test::method::<lambda_45e8626339fc29aadca2bf2dd3420511>
]
test\mytests\main.cpp(45): note: see reference to function template instantiation '_OutIt std::transform<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<const
foo *>>>,MyInsert,test::method::<lambda_45e8626339fc29aadca2bf2dd3420511>>(_InIt,_InIt,_OutIt,_Fn1)' being compiled
with
[
_OutIt=MyInsert,
_InIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<const foo *>>>,
_Fn1=test::method::<lambda_45e8626339fc29aadca2bf2dd3420511>
]
]
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么它(VS编译器)无法找到复制赋值运算符,它在明确提供时明确提供void *并返回MyInsert &.
挖掘更多(通过跟踪错误消息跟踪)
c:\program files (x86)\microsoft visual studio14.0\vc\include\xutility
和
c:\program files (x86)\microsoft visual studio14.0\vc\include\algorithm
还让我意识到std::transformation调用算法的实际函数,调用显式提供的复制赋值,之后它进入_Rechecked函数并进入xutility头部.
在此函数中,调用了复制赋值运算符,该运算符期望(输入为MyInsert&和输出为MyInsert&),并且由于它没有找到,因此它将错误消息显示为attempting to reference....
这个分析是否正确?如果没有,那么为什么无法编译在其他主要编译器上编译的代码?也许是一个错误?
PS
我正在使用的当前解决方法是MyInsert使用非引用成员删除类中的引用成员.
我无法理解为什么它(VS编译器)无法找到复制赋值运算符,它在明确提供时明确提供
void *并返回MyInsert &.
采用a的赋值运算符void*不是复制赋值运算符.
编译器确实尝试使用明确未明确提供的复制赋值运算符.也没有隐含地提供,因为有一个参考成员.
输出迭代器必须满足OutputIterator的要求,该要求必须满足Iterator的要求,而Iterator必须满足CopyAssignable的要求,不出所料地要求您拥有一个复制赋值运算符.这是MyInsert缺乏的东西.
为什么不能编译在其他主要编译器上编译的代码?
虽然输出迭代器必须满足要求,但标准库实现不需要检查是否满足要求.
希望概念的正式规范将成为未来标准的一部分,以便在这种情况下改进错误消息.
也许是一个错误?
该错误是代码中缺少的复制赋值运算符.VS和其他编译器在这方面都是标准兼容的.
我正在使用的当前解决方法是使用非引用成员删除MyInsert类中的引用成员.
通过删除引用成员,允许隐式声明复制赋值运算符.这就是它的原因.要在保持类型副本可分配的同时继续引用对象,请使用普通指针而不是引用.