::std
名前空間内のクラステンプレートは、通常、ユーザー定義型のプログラムに特化できます。私はこのルールに例外を見つけませんでしたstd::allocator
。
それで、std::allocator
私は自分のタイプに特化することを許可されていますか?また、許可されている場合、std::allocator
の主なテンプレートのすべてのメンバーを提供する必要がありstd::allocator_traits
ますか?
このプログラムを検討してください
#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();
}
libc ++(Clang with -std=c++17 -Wall -Wextra -pedantic-errors -O2 -stdlib=libc++
)を使用したこのプログラムの出力は次のとおりです。
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
そして、libstdc ++(Clang with -std=c++17 -Wall -Wextra -pedantic-errors -O2 -stdlib=libstdc++
)での出力は次のとおりです。
Allocating for 2
Allocating for 4
Constructing one
Constructing one
Allocating for 8
Constructing one
Constructing one
Constructing one
Constructing one
8
あなたがにlibstdc見ることができるように++いつもの過負荷尊重していないconstruct
私が提供していることを、私は削除した場合construct
、destroy
またはmax_size
メンバーを彼らはによって供給されるが、その後、プログラムはさらに、これらの不足しているメンバーに文句のlibstdc ++でコンパイルされませんstd::allocator_traits
。
プログラムには未定義の動作があるため、両方とも標準ライブラリは正しいですか、それともプログラムの動作は明確に定義されており、標準化ライブラリは私の専門分野を使用するために必要ですか?
std::allocator
自分の専門分野でまだ除外したのプライマリテンプレートのメンバーがいることに注意してください。それらも追加する必要がありますか?
正確には省略しました
using is_always_equal = std::true_type
これはstd::allocator_traits
、私のアロケータが空なので提供されますが、std::allocator
のインターフェイスの一部になります。
私はまた取り残さpointer
、const_pointer
、reference
、const_reference
、rebind
とaddress
、によって提供されているすべてはstd::allocator_traits
とのためのC ++ 17には非推奨std::allocator
のインタフェース。
std::allocator
のインターフェースに一致するようにこれらすべてを定義する必要があると思われる場合は、コードに追加されていると考えてください。