【问题标题】:Use noexcept operator depenendet使用 noexcept 运算符依赖
【发布时间】:2018-10-22 12:07:43
【问题描述】:

我想知道是否可以使用 C++11 的noexcept operator 来定义 e 的 noextcept 说明符。 G。调用另一个类的方法的析构函数(例如 std::allocator::deallocate):

template <class DelegateAllocator = std::allocator<uint8_t>>
class MyAllocator final {
 public:
  using allocator_type = DelegateAllocator;

  // ...

  ~MyAllocator() noexcept(noexcept(/* what to use */))) {
    if (memory_ != nullptr) {
      allocator_.deallocate(memory_, length_);
    }
  }

private: 
 allocator_type allocator_;   
 uint8_t* memory_;
 // ...
};

问题: 根据委托类型的使用方法(例如 std::allocator)定义 noexcept 的最佳解决方案是什么? 当存在不同的重载时,必须做些什么——如果可能的话——使用委托类型的方法(例如,当不只提供一个时,我将如何使用特定的解除分配实现)?

【问题讨论】:

    标签: c++ c++11 noexcept


    【解决方案1】:

    中,这很简单:

    ~MyAllocator() noexcept(noexcept(std::declval<allocator_type&>().deallocate( memory_, allocator_ ))) {
      if (memory_ != nullptr) {
        allocator_.deallocate(memory_, length_);
      }
    }
    

    Live example.

    但是在 中,“正确地”做是一件痛苦的事:

     ~MyAllocator() noexcept(noexcept(std::declval<allocator_type&>().deallocate( std::declval<uint8_t*&>(), std::declval<std::size_t&>() ))) {
        if (memory_ != nullptr) {
          allocator_.deallocate(memory_, length_);
        }
      }
    

    Live example.

    所以,升级到

    你也可以用hackily来做:

     ~MyAllocator() noexcept(noexcept(std::declval<allocator_type&>().deallocate( (uint8_t*)nullptr,1 ))) {
    

    但你必须小心,因为传递nullptr_t 可能会得到错误的答案(因此上述从nullptr 转换为uint8_t*,并避免使用0 作为文字)。

    【讨论】:

    • 谢谢!一个问题:为什么是std::declval&lt;allocator_type&amp;&gt;().deallocate( std::declval&lt;uint8_t*&amp;&gt;(), std::declval&lt;std::size_t&amp;&gt;() ) 而不是std::declval&lt;allocator_type&gt;().deallocate( std::declval&lt;uint8_t*&gt;(), std::declval&lt;std::size_t&gt;() )
    • @Sonic78 因为我们传递的是左值而不是右值。理论上,分配器可以区分它们并为右值而不是左值抛出,反之亦然。这将是一个疯狂的分配器,但在通用代码中,你的代码是防御性的。
    【解决方案2】:

    This stack overflow answer 向我指出了一种解决方案:

    ~StackAllocator() noexcept(noexcept(std::declval<allocator_type>().*&allocator_type::deallocate)) {
        if (memory_ != nullptr) {
          allocator_.deallocate(memory_, length_);
        }
    }
    

    只要该方法仅存在一个重载,此解决方案就可以工作。如果有人可以提供更好的解决方案(更好地阅读,可重用......)或也适用于具有重载的方法的解决方案,请提供。

    编辑/更新: 下面的一位同事和 Yakk 的回答提供了一个更好的解决方案,它还涵盖了不同的重载:

    ~StackAllocator() noexcept(noexcept(std::declval<allocator_type>().deallocate(std::declval<std::uint8_t*>(), std::declval<std::size_t>()))) 
    {
        if (memory_ != nullptr) {
            allocator_.deallocate(memory_, length_);
        }
    }
    
    猜你喜欢
    • 2015-10-17
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2017-07-13
    • 2016-01-17
    • 2019-03-11
    相关资源
    最近更新 更多