Question: I am reading "Effective Modern C++". In the item related to `std::unique_ptr` it's stated that if the custom deleter is a stateless object, then no size fees occur, but if it's a function pointer or `std::function` size fee occurs. Could you explain why?

Let's say that we have the following code:

```
auto deleter_ = [](int *p) { doSth(p); delete p; };
std::unique_ptr<int, decltype(deleter_)> up(new int, deleter_);

```

To my understanding, the `unique_ptr` should have an object of type `decltype(deleter_)` and assign `deleter_` to that internal object. But obviously that's not what's happening. Could you explain the mechanism behind this using smallest possible code example?

Answer: 
From a `unique_ptr` implementation:

```
template<class _ElementT, class _DeleterT = std::default_delete<_ElementT>>
class unique_ptr
{
public:
   // public interface...

private:

  // using empty base class optimization to save space
  // making unique_ptr with default_delete the same size as pointer

  class _UniquePtrImpl : private deleter_type
  {
  public:
     constexpr _UniquePtrImpl() noexcept = default;

     // some other constructors...

     deleter_type& _Deleter() noexcept
     { return *this; }

     const deleter_type& _Deleter() const noexcept
     { return *this; }

     pointer& _Ptr() noexcept
     { return _MyPtr; }

     const pointer _Ptr() const noexcept
     { return _MyPtr; }

  private:
     pointer   _MyPtr;

  };

  _UniquePtrImpl   _MyImpl;

};

```

The `_UniquePtrImpl` class contains the pointer and derives from the `deleter_type`. 

If the deleter happens to be stateless, the base class can be optimized so that it takes no bytes for itself. Then the whole `unique_ptr` can be the same size as the contained pointer - that is: the same size as an ordinary pointer.
In fact there *will* be a size penalty for lambdas that are not stateless, i.e., lambdas that capture one or more values.

But for non-capturing lambdas, there are two key facts to notice:

* The type of the lambda is *unique* and known only to the compiler.
* Non-capturing lambdas are stateless.

Therefore, the compiler is able to invoke the lambda purely based on its *type*, which is recorded as part of the type of the `unique_ptr`; no extra *runtime* information is required.

This is in fact why non-capturing lambdas are stateless. In terms of the size penalty question, there is of course nothing special about non-capturing lambdas compared to any other stateless deletion functor type.

Note that `std::function` is *not* stateless, which is why the same reasoning does *not* apply to it.

Finally, note that although stateless objects are typically required to have nonzero size in order to ensure that they have unique addresses, stateless base classes are *not* required to add to the total size of the derived type; this is called the empty base optimization. Thus `unique_ptr` can be implemented (as in Bo Perrson's answer) as a type that derives from the deleter type, which, if it's stateless, will not contribute a size penalty. (This may in fact be the *only* way to correctly implement `unique_ptr` without a size penalty for stateless deleters, but I'm not sure.)