2016-09-06 2 views
4

Следующий код хорошо компилируется на clang-3.8 и gcc 4.9.3.VS 2015 Update 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; 
} 

Однако, если скомпилировано приложение 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> 
     ] 
     ] 

Я не могу понять, почему он (VS Compiler) не может найти оператора присваивания копии, которая принимает 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....

Правильно ли этот анализ? Если нет, то почему не удается скомпилировать код, который компилируется на других основных компиляторах? Может быть, ошибка?

P.S

Текущая работа по всему, что я использую, чтобы удалить опорный элемент в MyInsert класса с нереференсного члена.

+0

@Oktalist ах, мой плохой тогда! – Yakk

ответ

5

Я не могу понять, почему он (VS Compiler) не может найти оператора присваивания копии, которая принимает void * и возвращает MyInsert &, когда явно один прямо предусмотрено.

Оператор присваивания, который принимает void* не копии оператора присваивания.

Компилятор пытается использовать оператор присваивания копий, который равен ясно не указывается явно. Это также неявно, потому что есть ссылочный элемент.

Выходной итератор должен соответствовать требованиям OutputIterator, которые должны отвечать требованиям Iterator, которые должны соответствовать требованиям CopyAssignable которые Unsurprisingly необходимо иметь оператор присваивания копии. Что-то, чего не хватает MyInsert.

Почему не удается скомпилировать код, который скомпилирован на других основных компиляторах?

Хотя выходной итератор должен удовлетворять требованиям, нет требования к стандартной реализации библиотеки для проверки выполнения требований.

Надеюсь, официальная спецификация концепций станет частью стандарта в будущем для улучшения сообщений об ошибках в таких случаях.

Возможно, ошибка?

Ошибка в операторе копирования в коде отсутствует. В этом отношении как VS, так и другие компиляторы являются стандартными.

Текущая работа вокруг того, что я использую, заключается в удалении ссылочного элемента в классе MyInsert с элементом без ссылки.

Удаляя ссылочный элемент, вы допускаете неявное объявление оператора присваивания копии. Вот почему это работает. Чтобы ссылаться на объект, сохраняя при этом тип копии, можно использовать простой указатель вместо ссылки.

+0

@NathanOliver Я не считаю это странным. Легко представить себе реализацию 'std :: transform', которая не нуждается в копировании, назначить выходной итератор. Вызов 'std :: transform' ** c ** ould должен быть ошибкой - как в: нет гарантии, что он будет работать, - но я не думаю, что стандарт требует, чтобы реализация проверяла требования к типу , – user2079303

+0

Да, я это понял. Проблема, которую я имею, это конструктор копирования, также должен быть удален, поэтому я не знаю, как он даже вызывает функцию, если мы прекратим копирование. – NathanOliver

+0

Я бы согласился, кроме [этого] (http://coliru.stacked-crooked.com/a/3051bb080f39558e), который должен потерпеть неудачу, но это не так. – NathanOliver

Смежные вопросы