Turn a non-blocking concurrent queue into a blocking concurrent queue
As a matter of consistency, we don't need to separate typename declaration for this private function void _push(T&amp;&amp; src), and we can depend on the typename declaration on the class level.

void _push(T&amp;&amp; src)
{
    bool notify = false;

    std::unique_lock&lt;std::mutex&gt; lock(_mtx);
    if (!hasData)
    {
        notify = true;
        hasData = true;
    }

    concurrency::concurrent_queue&lt;T&gt;::push(std::forward&lt;T&gt;(src));

    lock.unlock();

    if (notify)
        _cv.notify_one();
}

bool try_pop(T&amp; dest) is not part of public interface, so we can define it as private.
We can depend on std::forward and modify the interfaces for push as follows:

void push(const T&amp;&amp; src)
{
    _push(std::forward&lt;T&gt;(src));
}
void push(T&amp;&amp; src)
{
   _push(std::forward&lt;T&gt;(src));
}



After adapting all these changes it should be as follows. Please note I don't have the system to compile this code from my end.

#include &lt;concurrent_queue.h&gt;
/**
 * Single producer, single consumer blocking concurrent queue.
 */
template&lt;typename T&gt;
class SPSCBlockingQueue final : public concurrency::concurrent_queue&lt;T&gt;
{
  public:

    void push(const T&amp;&amp; src)
    {
        _push(std::forward&lt;T&gt;(src));
    }
    void push(T&amp;&amp; src)
    {
        _push(std::forward&lt;T&gt;(src));
    }

    /**
     * Pop an element from the head of the queue. This method will wait
     * until there is an item in the queue that can be dequeued.
     *
     * @return the dequeued item.
     */
    T pop()
    {
        T dest;
        try_pop(dest);
        return dest;
    }

  private:

    std::mutex _mtx;
    std::condition_variable _cv;
    bool hasData = false;

    bool try_pop(T&amp; dest)
    {
        std::unique_lock&lt;std::mutex&gt; lock(_mtx);

        auto res = concurrency::concurrent_queue&lt;T&gt;::try_pop(dest);
        if (!res)
        {
            // The queue must be empty.
            hasData = false;

            // Wait until there is some data...
            _cv.wait(lock, [&amp;] { return hasData; });

            // This should now work.
            res = concurrency::concurrent_queue&lt;T&gt;::try_pop(dest);
        }

        // res should be true.
        return res;
    }


    void _push(T&amp;&amp; src)
    {
        bool notify = false;

        std::unique_lock&lt;std::mutex&gt; lock(_mtx);
        if (!hasData)
        {
            notify = true;
            hasData = true;
        }

        concurrency::concurrent_queue&lt;T&gt;::push(std::forward&lt;T&gt;(src));

        lock.unlock();

        if (notify)
            _cv.notify_one();
    }
};