Ich habe versucht, eine benutzerdefinierte Speicherzuordner zu schaffen, die einen intelligenten Zeiger verwendet. Ich poste den Code nicht, weil er zu groß ist und nicht viel Information hinzufügt. Dann habe ich es mit einer std::vector
getestet. Es funktioniert perfekt auf Xcode. Aber als ich versuchte, den gleichen Code in Visual Studio 12 (2013) zu bauen, scheiterte der Build mit dem folgenden Fehler:Speicherzuordner mit benutzerdefinierten Zeigertyp
...vector(873): error C2660: '
std::_Wrap_alloc< my_allocator<int> >::construct
' : function does not take 2 arguments
das Problem ist in push_back Methode:
void push_back(value_type&& _Val)
{
....
this->_Getal().construct(this->_Mylast,
_STD forward<value_type>(this->_Myfirst[_Idx]));
....
}
Die Fehlermeldung ist ein bisschen verwirrend. Wirkliches Problem ist, dass this->_Mylast
vom Typ my_allocator<int>::pointer
, die eine Smartpointer ist, und konstruieren Methode erwartet int*
.
Also, die Frage ist einfach: Was sind die Anforderungen Typen in einem benutzerdefinierten Speicherzuordner verwendet, um den Zeiger? Sollte X::pointer
in einen rohen Zeiger konvertierbar sein? Wenn ja, macht es sie ziemlich nutzlos.
Eigentlich würde ich diese Zeile Code erwarten aussehen:
this->_Getal().construct(addressof(*(this->_Mylast)),
_STD forward<value_type>(this->_Myfirst[_Idx]));
Lasst uns versuchen, eine Antwort in C++ Standard zu finden, die sagt:
[17.6.3.5-5] An allocator type X shall satisfy the requirements of CopyConstructible (17.6.3.1). The
X::pointer
,X::const_pointer
,X::void_pointer
, andX::const_void_pointer
types shall satisfy the requirements of NullablePointer (17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception.X::pointer
andX::const_pointer
shall also satisfy the requirements for a random access iterator (24.2)
Wenn wir einen Blick auf NullablePointer nehmen reqs, fügen sie einige andere Anforderungen:
[17.6.3.3] A NullablePointer type is a pointer-like type that supports null values. A type P meets the requirements of NullablePointer if:
(1.1) — P satisfies the requirements of EqualityComparable, DefaultConstructible, CopyConstructible, CopyAssignable, and Destructible...
Wenn ich Random Access Iterator re überprüfen Ich finde auch keine explizite Erwähnung des Castings für einen rohen Zeiger. Aber an einigen Stellen wird der Ansatz mit addressof
verwendet (z. B. 24.2.1-5).
Auch ist es nicht die einzige Stelle in Microsofts std::vector
Implementierung, wo X::pointer
und rohe Zeiger als gleich angenommen werden. Ich frage mich, was ich vermisse?
EDIT: Ich werde ein Stück my_allocator deffinition hier hinzufügen:
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);
};
Können Sie uns alle Typdefinitionen in Ihrem Allokator zur Verfügung stellen? Z.B. 'const_pointer' und so weiter? (Es würde mich absolut nicht überraschen, wenn die Standardbibliothek von VC++ nicht vollständig konform ist) – Columbo
Wahrscheinlich ist die VC++ Standardbibliothek fehlerhaft. Ich dachte, dass die Konstruktion von 'std'-Objekten über' allocator_traits_construct' anstatt direkt 'allocator :: construct' erfolgen sollte. – Walter
@Columbo, Ich habe den gewünschten Code hinzugefügt. – Maxym