Klassenvorlagen im ::stdNamespace können im Allgemeinen durch Programme für benutzerdefinierte Typen spezialisiert werden. Ich habe keine Ausnahme von dieser Regel für gefunden std::allocator.
Darf ich mich also auf std::allocatormeine eigenen Typen spezialisieren? Und wenn ich darf, muss ich dann alle Mitglieder der std::allocatorprimären Vorlage bereitstellen , da viele von ihnen von bereitgestellt werden können std::allocator_traits(und daher in C ++ 17 veraltet sind)?
Betrachten Sie dieses Programm
#include<vector>
#include<utility>
#include<type_traits>
#include<iostream>
#include<limits>
#include<stdexcept>
struct A { };
namespace std {
template<>
struct allocator<A> {
using value_type = A;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using propagate_on_container_move_assignment = std::true_type;
allocator() = default;
template<class U>
allocator(const allocator<U>&) noexcept {}
value_type* allocate(std::size_t n) {
if(std::numeric_limits<std::size_t>::max()/sizeof(value_type) < n)
throw std::bad_array_new_length{};
std::cout << "Allocating for " << n << "\n";
return static_cast<value_type*>(::operator new(n*sizeof(value_type)));
}
void deallocate(value_type* p, std::size_t) {
::operator delete(p);
}
template<class U, class... Args>
void construct(U* p, Args&&... args) {
std::cout << "Constructing one\n";
::new((void *)p) U(std::forward<Args>(args)...);
};
template<class U>
void destroy( U* p ) {
p->~U();
}
size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max()/sizeof(value_type);
}
};
}
int main() {
std::vector<A> v(2);
for(int i=0; i<6; i++) {
v.emplace_back();
}
std::cout << v.size();
}
Die Ausgabe dieses Programms mit libc ++ (Clang with -std=c++17 -Wall -Wextra -pedantic-errors -O2 -stdlib=libc++) ist:
Allocating for 2
Constructing one
Constructing one
Allocating for 4
Constructing one
Constructing one
Allocating for 8
Constructing one
Constructing one
Constructing one
Constructing one
8
und die Ausgabe mit libstdc ++ (Clang with -std=c++17 -Wall -Wextra -pedantic-errors -O2 -stdlib=libstdc++) ist:
Allocating for 2
Allocating for 4
Constructing one
Constructing one
Allocating for 8
Constructing one
Constructing one
Constructing one
Constructing one
8
Wie Sie sehen können libstdc ++ ehren nicht immer die Überlastung , constructdass ich zur Verfügung gestellt haben , und wenn ich die entfernen construct, destroyoder max_sizeMitglieder, dann wird das Programm nicht einmal mit libstdc ++ beschwerte sich über diese fehlenden Mitglieder kompilieren, obwohl sie geliefert werden std::allocator_traits.
Hat das Programm ein undefiniertes Verhalten und sind daher beide Standardbibliotheken korrekt, oder ist das Verhalten des Programms genau definiert und die Standardbibliothek für die Verwendung meiner Spezialisierung erforderlich?
Beachten Sie, dass es einige Mitglieder aus std::allocatorder primären Vorlage gibt, die ich in meiner Spezialisierung noch ausgelassen habe. Muss ich sie auch hinzufügen?
Um genau zu sein, habe ich ausgelassen
using is_always_equal = std::true_type
std::allocator_traitsDies wird von bereitgestellt, da mein Allokator leer ist, aber Teil der std::allocatorSchnittstelle wäre.
Ich verließ auch heraus pointer, const_pointer, reference, const_reference, rebindund address, die alle durch zur Verfügung gestellt werdenstd::allocator_traits und in C ++ als veraltet 17 für std::allocator‚s - Schnittstelle.
Wenn Sie der Meinung sind, dass alle diese Elemente so definiert werden müssen, dass sie mit der std::allocatorBenutzeroberfläche übereinstimmen , sollten Sie sie dem Code hinzufügen.