Любая идея, почему a1 = a2 не работает, но работает a2 = a1. Должна быть функция в шаблоне интеллектуального указателя, который выполняет преобразование? Который из них?
#include "stdafx.h"
#include<memory>
class TestClass
{
public:
int a ;
};
typedef std::shared_ptr<TestClass> TestSP;
typedef std::shared_ptr<const TestClass> TestConstSP;
int _tmain(int argc, _TCHAR* argv[])
{
TestSP a1 = TestSP();
TestConstSP a2 = TestConstSP();
//a1 =a2; //error C2440: '<function-style-cast>' : cannot convert from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty>'
a2=a1;
return 0;
}
Это связано с использованием const
. Если у вас есть указатель const
' const_ptr
' и указатель non const
' non_const_ptr
', это нормально:
const_ptr = non_const_ptr; // const_ptr doesn't allow modifying the pointed value, while non_const_ptr does.
Но это запрещено:
non_const_ptr = const_ptr; // const_ptr is 'const'. Allowing non_const_ptr to modify the pointed value would'n respect the 'const' contract.
И следующее будет работать:
non_const_ptr = (type *) const_ptr; // You have the right to do that as you explicitely break the contract.
// The programmer is the boss. This is a bit ugly though.
Точно такая же логика применяется к вашему примеру.
Это интересно, и похоже, что MSVC реализовал стандарт для письма здесь. Само присваивание указано в §20.8.2.2.3 [util.smartptr.shared.assign]/p1-3:
shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
Эффекты: эквивалент
shared_ptr(r).swap(*this)
.Возвращает:
*this
.[Примечание. Обновления подсчета использования, вызванные созданием и уничтожением временных объектов, не являются наблюдаемыми побочными эффектами, поэтому реализация может удовлетворять эффектам (и подразумеваемым гарантиям) с помощью различных средств без создания временного.
<example omitted>
]
Соответствующий конструктор указан в §20.8.2.2.1 [util.smartptr.shared.const]/p17-19:
shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Требуется: второй конструктор не должен участвовать в разрешении перегрузки, если
Y*
неявно конвертируется вT*
.Эффекты: если
r
пуст, создается пустой объектshared_ptr
; в противном случае создается объектshared_ptr
который имеет право собственности наr
.Постусловия:
get() == r.get() && use_count() == r.use_count()
.
Поскольку const TestClass *
неявно конвертируется в TestClass *
, шаблонный конструктор не участвует в разрешении перегрузки, что делает shared_ptr(r)
плохо сформированным, поскольку нет соответствующего конструктора.
Edit: Я вижу путаницу. VS2012 довольно плохо разработан для сообщений об ошибках компилятора. Полное сообщение об ошибке, испускаемое компилятором:
error C2440: '<function-style-cast>' : cannot convert from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty>'
with
[
_Ty=const TestClass
]
and
[
_Ty=TestClass
]
Важно отметить, что два _Ty
в выводе ошибки относятся к разным типам. Окно списка ошибок в VS2012, однако, обрезает это только в первой строке и теряет эту важную информацию. Вы должны посмотреть на вывод сборки для полного сообщения об ошибке.
shared_ptr<const TestClass>
и shared_ptr<TestClass>
. Верхний уровень const (как в const std::shared_ptr<TestClass>
) не имеет значения для преобразования. VS2013 выдает мне error C2440: '<function-style-cast>' : cannot convert from 'const std::shared_ptr<const TestClass>' to 'std::shared_ptr<TestClass>'