Использовать зависимый оператор noexcept

Интересно, можно ли использовать оператор C++11 noexcept для определения спецификатор noextcept e. грамм. деструктор, вызывающий метод другого класса (например, 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)? Что нужно сделать, когда это возможно, чтобы использовать методы делегированного типа, когда существуют разные перегрузки (например, как мне использовать конкретную реализацию освобождения, если не предоставлена ​​только одна)?


person Sonic78    schedule 22.10.2018    source источник


Ответы (2)


В c++14 это так просто:

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

Живой пример.

Но в c++11 это боль сделать "правильно":

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

Живой пример.

Итак, обновите до

Этот ответ о переполнении стека указал мне на одно решение:

~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_);
    }
}
person Sonic78    schedule 22.10.2018
comment
stackoverflow.com/questions/17874489/ - person rustyx; 22.10.2018