2016-12-02 29 views
14

Tính đến thời điểm viết bài, đưa ra một cppreference reasonably simple definition của std::in_place_t gia đình:std :: in_place_t và bạn bè trong C++ 17

struct in_place_t { 
    explicit in_place_t() = default; 
}; 
inline constexpr std::in_place_t in_place{}; 

template <class T> 
struct in_place_type_t { 
    explicit in_place_type_t() = default; 
}; 

template <class T> 
inline constexpr std::in_place_type_t<T> in_place_type{}; 

template <size_t I> struct in_place_index_t { 
    explicit in_place_index_t() = default; 
}; 

template <size_t I> 
inline constexpr in_place_index_t<I> in_place_index{}; 

Tuy nhiên, dự thảo mới nhất của chuẩn C++ 17 linked from isocpp.org có định nghĩa phức tạp hơn (phần 20.2.7, trang 536):

struct in_place_tag { 
    in_place_tag() = delete; 
}; 
using in_place_t = in_place_tag(&)(unspecified); 

template <class T> 
using in_place_type_t = in_place_tag(&)(unspecified <T>); 

template <size_t I> 
using in_place_index_t = in_place_tag(&)(unspecified <I>); 

in_place_tag in_place(unspecified); 

template <class T> 
in_place_tag in_place(unspecified <T>); 

template <size_t I> 
in_place_tag in_place(unspecified <I>); 

Phiên bản đầu tiên là đơn giản và dễ hiểu, nhưng phiên bản thứ hai khá mờ nhạt đối với tôi. Vì vậy, các câu hỏi:

  • Phiên bản nào là đúng, sau Issaqua (tháng 11 năm 2016)? (Có lẽ là thứ hai, nhưng có thể là N4606 vẫn chưa được cập nhật sau cuộc họp và cppreference mới nhất có.)

  • Rõ ràng điều này đã thay đổi tại một thời điểm nào đó; có ai có liên kết đến một bài báo đề cập đến sự thay đổi không?

  • Quan trọng nhất, bất kỳ ai cũng có thể giải thích cách phiên bản thứ hai được dự định hoạt động? Việc triển khai mẫu sẽ như thế nào?

+0

Hoàn toàn không có cấu trúc, nhưng tôi _so_ không bận tâm rằng tôi đã dừng theo tiêu chuẩn C++. Thật là một mớ hỗn độn. –

+0

@LightnessRacesinOrbit: Này, nó chứng minh quá trình tiêu chuẩn đã được cải thiện. Nhớ 'vector '? Điều đó thực sự đã được chuẩn hoá; điều này đã thực sự được hoàn nguyên. Vì vậy, đó là tiến bộ. –

+0

FYI, cppreference có lịch sử sửa đổi bạn có thể kiểm tra và mọi bản nháp đang hoạt động được đề ngày trên trang đầu tiên. –

Trả lời

14

Phiên bản đầu tiên là phiên bản đầu tiên, hiện tại và sẽ có khả năng là phiên bản kết thúc bằng C++ 17.

Phiên bản thứ hai là an attempt để cho phép một để viết in_place ở khắp mọi nơi, không có gì, với một loại, hoặc với một chỉ số:

std::optional<int> o(std::in_place, 1); 
std::any a(std::in_place<int>, 1); 
std::variant<int, int> v(std::in_place<0>, 1); 

Cách duy nhất để làm cho công việc cú pháp này là làm cho in_place một quá tải và điều đó cũng yêu cầu tạo các bí danh in_place*_t để tham chiếu đến các hàm. Không có sự khác biệt thực hiện nào khác - các hàm in_place không có nghĩa là được gọi, chúng chỉ tồn tại để tham chiếu đến chúng có thể được truyền xung quanh dưới dạng thẻ và khớp với các loại _t tương ứng.

Tuy nhiên nó quá thông minh và gây ra các vấn đề riêng (ví dụ, không giống như các loại thẻ đơn giản, chúng không phản ứng tốt khi bị decay 'd và đồng nhất , là tên hàm quá tải, hành vi sai trái với giao nhận hoàn hảo: std::optional<std::optional<int>> o(std::in_place, std::in_place); không làm việc vì trình biên dịch không thể giải quyết thứ hai), do đó it got backed out ở Issaquah, và bây giờ bạn phải viết

std::optional<int> o(std::in_place, 1); 
std::any a(std::in_place_type<int>, 1); 
std::variant<int, int> v(std::in_place_index<0>, 1); 

Một chút ít đẹp, nhưng lành mạnh hơn.

+0

Câu trả lời hay, cảm ơn rất nhiều. –

Các vấn đề liên quan