使用noexcept运算符depenendet

时间:2018-10-22 12:07:43

标签: c++ c++11 noexcept

我想知道是否可以使用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_;
 // ...
};

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

2 个答案:

答案 0 :(得分: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

因此,升级到

您也可以巧妙地做到这一点:

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

但是您必须要小心,因为传递nullptr_t可能会给您错误的答案(因此,上述内容从nullptruint8_t*,并且避免将0用作文字)。

答案 1 :(得分:0)

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_);
    }
}