1

I'm trying to provide a get_deleter() for my lock-free allocator class template (code is here). The deleter is something like

template <typename T>
struct deleter {
  allocator<T>& alloc;
  void operator()(T* p) const noexcept {
    p->~T();
    alloc.deallocate(p);
  }
};

Note that alloc should not be const, since deallocate() is not const, which aligns with std::allocator::deallocate(). Now, I'm not sure whether my allocator::get_deleter() should be const. The dilemma is as follows:

1. Rationale for being const: The method itself doesn't modify *this, and is thread-safe (also see Does const mean thread-safe in C++11?).

2. Rationale for not being const: The method returns a deleter that can be used to modify *this. Also avoids const_cast() that is necessary if the method is const.

Any suggestion or idea? Personally, I'm in favor of const.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • I would personally favor the intent and not mark it as `const` if marking it as `const` would mean I can delete a const object without getting any warning. Doesn't sound like something I want to allow. Perhaps provide both? – spectras Mar 13 '18 at 11:29
  • @spectras But you can call the destructor of a `const` object, right? Yet, `operator delete()` doesn't accept `const` pointer. What a dilemma :( – Lingxi Mar 13 '18 at 11:32
  • That's an explicit exception: *“A destructor can be invoked for a const, volatile or const volatile object. [...] const and volatile semantics are not applied on an object under destruction”*. See https://stackoverflow.com/a/2271055/3212865 – spectras Mar 13 '18 at 11:37
  • @spectras Then I think this exception should also apply to deallocation, otherwise the memory of `const` objects could not be reclaimed. The `deleter` does just these two things: destroy and deallocate. – Lingxi Mar 13 '18 at 11:40
  • I understand your point. It's true one can delete a const object. And in fact your deleter is running the destructor so the same argument used to justify destruction exception could indeed apply. – spectras Mar 13 '18 at 11:50

1 Answers1

1

Don't const_cast<allocator &>(*this)

You don't know if anyone is going to have a const allocator<...> value and get undefined behaviour. Even if you don't, you are lying about how const it really is.

allocator::get_deleter can't be const without a const_cast, so it shouldn't.

See it live

Caleth
  • 52,200
  • 2
  • 44
  • 75