2012-10-21 16 views
5

Tôi muốn thực hiện một tùy chọn giống như Scala/Haskell giống như lớp C++. Vì lý do hiệu quả, tôi không muốn sử dụng bộ nhớ được phân bổ động, cũng như tôi không muốn sử dụng đa hình. Ngoài ra, tôi không muốn bất kỳ đối tượng nào của kiểu được nhúng được tạo nếu Option là None.Tùy chọn/Có thể lớp cho C++

Ai có thể cho tôi biết liệu cách tiếp cận sau có thể gây ra sự cố không? Tôi phải phân bổ bộ nhớ tĩnh cho đối tượng nhúng trong lớp Option, nhưng tôi không thể định nghĩa một trường thành viên của kiểu được nhúng, vì điều này sẽ được khởi tạo khi tạo đối tượng Option ngay cả khi Option là None.

template <typename T> 
class Option { 
private: 
    uint8_t _storage [sizeof (T)]; 
    T * _embedded; 
public: 
    Option() : _embedded (nullptr) { 
    } 

    Option (const T & obj) : _embedded (new (_storage) T (obj)) { 
    } 

    Option (const Option<T> & other) 
    : _embedded (
     other->_embedded ? new (_storage) T (other->_embedded) : nullptr 
    ) { 
    } 

    // ... 

    ~Option() { 
     if (_embedded) _embedded->~T(); 
    } 
}; 
+2

Bạn có thể kiểm tra cách [Boost.Optional] (http://www.boost.org/doc/libs/1_51_0/libs/optional/doc/html/index.html) được triển khai. – kennytm

+0

Cảm ơn gợi ý. Tôi nên biết Boost có nó. – JohnB

+1

Nó thực sự là một đại diện thông minh. Bạn sẽ cần phải đối phó với ** gán ** quá, nhưng nếu không tôi thực sự thích ý tưởng trực tiếp lưu trữ một con trỏ chứ không chỉ là một boolean. Làm cho mọi thứ dễ dàng hơn sau đó chắc chắn. –

Trả lời

3

Tôi không nghĩ rằng mảng được yêu cầu phải được sắp xếp theo cùng một cách các lớp đối tượng có thể yêu cầu. Trong thực tế, tôi sẽ không mong đợi bất kỳ vấn đề, trừ khi loại có yêu cầu liên kết hài hước.

Với C++ 2011 bạn có thể sử dụng union để giữ biểu diễn thực sự, mặc dù bạn vẫn cần quản lý thời gian sống của đối tượng được giữ. Có một số boost::optional<T> và một số proposal để thêm một loại tương tự vào bản sửa đổi tiếp theo của tiêu chuẩn.

+0

Bạn có thể sử dụng boost :: aligned_storage để có được sự liên kết chính xác của bộ đệm. – mauve

+0

Trả về bộ nhớ không liên kết từ vị trí mới là UB theo câu trả lời cho câu hỏi này: http://stackoverflow.com/questions/11781724/do-i-really-have-to-worry-about-alignment-when-using-placement -new-operator – PiotrNycz

+0

Trên thực tế, trong C++ 11 tôi mong đợi 'std :: aligned_storage' sẽ được sử dụng. Nó được tạo ra đặc biệt để yêu cầu lưu trữ thô với kích thước chính xác * và căn chỉnh *. –

1

Đối với tôi điều này có vẻ tốt, ngoại trừ:

uint8_t _storage [sizeof(T)/sizeof(uint8_t)]; 

Option (const Option & other) 
    : _embedded (other->_embedded ? new (_storage)T(other->_embedded) : nullptr) 
{ 
} 
+0

Điều gì về 'char _storage [sizeof (T)];' vì ['char' luôn luôn là 1] (http://en.cppreference.com/w/cpp/language/sizeof) về kích thước? – Wolf