2013-07-25 11 views
6

C++ 11 cung cấp lớp std::allocator_traits là cách tiêu chuẩn để sử dụng các trình phân bổ. Hàm tĩnh std::allocator_traits::construct() lấy một con trỏ đến nơi đối tượng sẽ được tạo. Tuy nhiên, hàm std::allocator_traits::allocate() tĩnh trả về giá trị allocator::pointer, chỉ có hành vi giống như một con trỏ nhưng không nhất thiết phải là một con trỏ (nói chung, mặc dù std::allocator::pointer được yêu cầu làm con trỏ).allocator_traits :: construct() vs allocator_traits :: allocate()

Làm cách nào để sử dụng phân bổ và xây dựng các phương pháp tĩnh nếu, nói chung, chúng sẽ hoạt động với các loại không tương thích? Chúng có thể được sử dụng chỉ khi loại pointer thực sự có thể chuyển đổi thành con trỏ đơn giản bình thường không?

+0

+1 Đây là một câu hỏi đặc biệt sâu sắc tại thời điểm này. Có rất ít lập trình viên C++ khám phá những vùng biển này. Người triển khai phải. Điều này dẫn tôi đến đặt câu hỏi: Bạn có phải là std :: lib implementor không? –

+0

@HowardHinnant: Cảm ơn! Câu hỏi được kết nối với thiết kế của một lớp vectơ nhỏ với một vài chuông và còi trên '' std :: vector'' (ví dụ, tự động sử dụng bộ nhớ tĩnh lên đến một vài phần tử, hỗ trợ cho SSE và các hướng dẫn vector khác , v.v.) Chỉ muốn cố gắng làm những điều theo cách "thích hợp" đối với hỗ trợ cấp phát. – bluescarni

Trả lời

4

Có hai kỹ thuật để thực hiện việc này tùy thuộc vào những gì bạn có vào lúc này.

Nếu bạn có một biểu thức vế trái, nói lĩnh vực giá trị trong một nút, sau đó bạn có thể sử dụng std :: AddressOf như vậy:

allocator_traits<allocator_type>::construct(alloc, std::addressof(ptr->value), ...); 

nơi ptr là một allocator_type::pointer.

Tuy nhiên nếu bạn không có một trường để dereference và bạn muốn chuyển đổi một allocator_type::pointer-T*, có một mẹo bạn cần phải thực hiện đầu tiên:

template <class T> 
inline 
T* 
to_raw_pointer(T* p) noexcept 
{ 
    return p; 
} 

template <class Pointer> 
inline 
typename std::pointer_traits<Pointer>::element_type* 
to_raw_pointer(Pointer p) noexcept 
{ 
    return p != nullptr ? ::to_raw_pointer(p.operator->()) 
         : nullptr; 
} 

Và bây giờ bạn có thể nói:

allocator_traits<allocator_type>::construct(alloc, to_raw_pointer(ptr), ...); 
+0

Oh wow, người ta không bao giờ kết thúc việc học ... Ngữ nghĩa của '' operator ->() '' là khá tâm boggling: D – bluescarni

+0

Chúc mừng bằng cách này, đánh dấu câu trả lời là chấp nhận. – bluescarni

+0

tại sao bạn viết '::' trước 'to_raw_pointer (p.operator ->())'? Có nguy cơ nào mà ADL sẽ gây nhiễu nếu không, hay chỉ là một thói quen? Tôi sẽ cho rằng khi cả hai tình trạng quá tải đều ở cùng một không gian tên thì sẽ không thành vấn đề. – TemplateRex