In my opinion, calling notify_one (or rather notify_all if you were to extend your buffer to multiple producers/consumers) on both condition variables in the destructor before the calls to join would be the preferred solution for several reasons:
Firstly, this matches the way that conditional variables are typically used: By setting quit_, you change the state that the producer/consumer threads are interested in and wait for, so you should notify them of the state change.
Furthermore, notify_one should not be a very costly operation.
Also, in a more realistic application, it could be the case that in between the production of two elements, there is a delay; in that case you may not want to block in your destructor until the consumer notices it has to cancel as soon as the next element is enqueued; in the example code, that does not occur, as far as I can see.