2017-02-05 10 views
10

std::variant cung cấp các chức năng truy cập sau:không an toàn, `noexcept` và không overhead cách tiếp cận 'std :: variant`

  • std::get_if: lấy con trỏ-variant, trở con trỏ để thay thế .

    template <std::size_t I, typename... Ts> 
    auto* std::get_if(std::variant<Ts...>* pv) noexcept; 
    
    • Nếu pv không phải là một con trỏ null và pv->index() == I, trả về một con trỏ đến giá trị được lưu trữ trong các biến thể được trỏ đến bởi pv. Nếu không, trả về một giá trị con trỏ null.

      Điều này có nghĩa rằng việc thực hiện get_if 's khoảng trông như thế này:

      template <std::size_t I, typename... Ts> 
      auto* std::get_if(std::variant<Ts...>* pv) noexcept 
      { 
          if(pv == nullptr) return nullptr; 
          if(pv->index() != I) return nullptr; 
          return &(pv->real_get<I>()); 
      } 
      
  • std::get: lấy tham khảo-variant, trở tham khảo để thay thế, throw trên không hợp lệ truy cập.

    template <std::size_t I, typename... Ts> 
    auto& std::get(std::variant<Ts...>& v); 
    
    • Nếu v.index() == I, trả về một tham chiếu đến các giá trị được lưu trữ trong v. Nếu không, hãy ném std::bad_variant_access.

      Điều này có nghĩa rằng việc thực hiện get 's khoảng trông như thế này:

      template <std::size_t I, typename... Ts> 
      auto& std::get(std::variant<Ts...>& v) 
      { 
          if(v.index() != I) throw std::bad_variant_access{}; 
          return v.real_get<I>(); 
      } 
      

Tôi muốn một chức năng truy cập an toàn rằng:

  • noexcept.

  • Mất tham chiếu đến variant, tránh bất kỳ pv == nullptr kiểm tra.

  • hành vi chưa xác định nếu v.index() != I.

Tại sao? Bởi vì có thể có một số tình huống mà tôi chắc chắn 100% rằng một cá thể variant cụ thể chứa một loại cụ thể trong đường dẫn mã. Ngoài ra, sẽ hữu ích khi viết mã chung đã được kiểm tra riêng v.index() != I(ví dụ: viết visit của riêng tôi).thực hiện

Ví dụ:

template <std::size_t I, typename... Ts> 
auto& unsafe_get(std::variant<Ts...>& v) 
{ 
    return v.real_get<I>(); 
} 

Có một cái gì đó như thế này trong tiêu chuẩn? Tôi không thể tìm thấy nó. Nếu không, là điều này có thể triển khai cho std::variant hay tôi cần triển khai triển khai variant của riêng mình?

+0

Tôi không nghĩ thư viện chuẩn sẽ cung cấp/cho phép chức năng loại không an toàn như vậy. – cpplearner

+0

Có lẽ đáng để hỏi về std-thảo luận. Điều này luôn có thể được đề xuất như là một phần mở rộng trong tương lai. –

+0

Tại sao tình trạng không có ngoại lệ lại quan trọng đến mức nào, hoặc là gì? Làm thế nào bạn đã thử nghiệm này? – EricWF

Trả lời

6

Như được chỉ ra bởi @ T.C. trong các nhận xét, desiderata thứ nhất và thứ ba của bạn không tương thích lẫn nhau. Điều này đã được viết ra trong N3279, có tiêu đề "Bảo thủ sử dụng noexcept trong Thư viện".

Về cơ bản có hai loại hợp đồng: hẹp và rộng. Hợp đồng rộng cho một chức năng hoặc hoạt động không chỉ định bất kỳ hành vi không xác định nào. Hợp đồng như vậy không có điều kiện tiên quyết. Chỉ các hàm có hợp đồng rộng được đánh dấu là noexcept trong Thư viện chuẩn.

OTOH, hẹp Hợp đồng là hợp đồng không rộng. Hợp đồng thu hẹp đối với một chức năng hoặc kết quả hoạt động trong hành vi không xác định khi được gọi theo cách vi phạm hợp đồng được ghi nhận. Chúng không thể được đánh dấu là noexcept. Thay vào đó, điều tốt nhất bạn có thể mong đợi là chúng được ghi nhận là "Ném: Không có gì".

Dường như bạn đã hết may mắn và không có quyền truy cập không được kiểm soát nào được cung cấp trong các đề xuất hiện tại cho std::variant.

1

Tôi nghĩ bạn phải tự mình thực hiện toàn bộ biến thể. Mặc dù các công đoàn không hạn chế có thể hữu ích - ít nhất họ cũng giải quyết việc đặt nhiều loại trong cùng một vị trí với vấn đề liên kết được xử lý.

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