Я попытался создать специализированный распределитель памяти, который использует интеллектуальный указатель. Я не размещаю код, потому что он слишком большой и не содержит большой информации. Затем я протестировал его с помощью std::vector
. Он отлично работает на Xcode. Но когда я попытался создать тот же код в Visual Studio 12 (2013), сбой сборки произошел со следующей ошибкой:
... vector (873): ошибка C2660: '
std::_Wrap_alloc< my_allocator< int > >::construct
': функция не принимает 2 аргумента
проблема заключается в методе push_back:
void push_back(value_type&& _Val)
{
....
this->_Getal().construct(this->_Mylast,
_STD forward<value_type>(this->_Myfirst[_Idx]));
....
}
Сообщение об ошибке немного запутанно. Реальная проблема заключается в том, что this->_Mylast
имеет тип my_allocator< int >::pointer
, который является умным указателем, а метод построения ожидает int*
.
Итак, вопрос прост: каковы требования к типам указателей, которые используются в специализированном распределителе памяти? Должен ли X::pointer
быть конвертируемым в необработанный указатель? Если да, это делает их довольно бесполезными.
На самом деле я ожидал бы, что строка кода выглядит следующим образом:
this->_Getal().construct(addressof(*(this->_Mylast)),
_STD forward<value_type>(this->_Myfirst[_Idx]));
Попробуйте найти ответ в стандарте С++, в котором говорится:
[17.6.3.5-5] Тип распределителя X должен удовлетворять требованиям CopyConstructible (17.6.3.1). Типы
X::pointer
,X::const_pointer
,X::void_pointer
иX::const_void_pointer
должны удовлетворять требованиям NullablePointer (17.6.3.3). Никакой конструктор, оператор сравнения, операция копирования, операция перемещения или операция свопинга на этих типах не должны выходить из-за исключения.X::pointer
иX::const_pointer
также должны удовлетворять требованиям для итератора произвольного доступа (24.2)
Если мы посмотрим на NullablePointer reqs, они добавят несколько других требований:
[17.6.3.3] Тип NullablePointer - это указательный тип, поддерживающий нулевые значения. Тип P соответствует требованиям NullablePointer, если:
(1.1) - P удовлетворяет требованиям EqualityComparable, DefaultConstructible, CopyConstructible, CopyAssignable и Destructible...
Если я проверяю требования к итератору произвольного доступа, я также не нахожу никакого явного упоминания о его литье к необработанному указателю. Но в нескольких местах используется подход с addressof
(например, 24.2.1-5).
Кроме того, это не единственное место в реализации Microsoft std::vector
, где X::pointer
и необработанный указатель считаются равными. Мне интересно, что мне не хватает?
EDIT: я добавлю часть my_allocator deffinition здесь:
class my_allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef my_ptr<T> pointer;
typedef my_ptr<const T> const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef my_ptr<void> void_pointer;
typedef my_ptr<const void> const_void_pointer;
<constructors>
pointer allocate(size_type n, const_void_pointer = nullptr);
void deallocate(const pointer& ptr, size_type elements_num);
};