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

0
Sonic78 22 Окт 2018 в 15:07

2 ответа

Лучший ответ

В это так просто:

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

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

Но в Больно делать "правильно":

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

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

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

Вы также можете сделать это хакерским способом:

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

Но вы должны быть осторожны, потому что передача nullptr_t может привести к неправильному ответу (отсюда приведенное выше приведение от nullptr к uint8_t* и избегание использования 0 в качестве литерала) ,

1
Yakk - Adam Nevraumont 22 Окт 2018 в 16:14

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

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

Это решение работает, пока существует только одна перегрузка для метода. Если кто-то может предоставить лучшее решение (лучше для чтения, многоразового использования ...) или решение, которое также работает с методами, имеющими перегрузки, предоставьте его.

< Сильный > Edit / Update : Коллега и ответ от 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_);
    }
}
0
Sonic78 23 Окт 2018 в 11:35
52928983