我想知道是否可以使用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)的最佳解决方案是什么? 当存在不同的重载时(如果可能的话),必须做些什么才能使用委托类型的方法(例如,当不只提供一个实现时,我将如何使用特定的解除分配实现)?
答案 0 :(得分:1)
在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_);
}
}
因此,升级到c++14。
您也可以巧妙地做到这一点:
~MyAllocator() noexcept(noexcept(std::declval<allocator_type&>().deallocate( (uint8_t*)nullptr,1 ))) {
但是您必须要小心,因为传递nullptr_t
可能会给您错误的答案(因此,上述内容从nullptr
到uint8_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_);
}
}