Scoped time sink implementation
Allow users to customize your TimeSink class

We achieve this by making it a template class:

template &lt;typename TimeUnit, typename Clock&gt;
class time_sink;


This will allow your class to be used in different scenarios; it removes restrictions.

Since the TimeUnit template parameter is the one most likely to be changed, we can provide a default argument for Clock:

template &lt;typename TimeUnit, typename Clock = std::chrono::steady_clock&gt;
class time_sink;


Your destructor can be simplified

Instead of doing...

time_point end = std::chrono::steady_clock::now();
auto elapsed = end-start;
auto remaining_time_to_sleep = min_duration - elapsed;
if (remaining_time_to_sleep &gt; epsilon)
{
    std::this_thread::sleep_for(remaining_time_to_sleep);
}


...we can do:

auto time_spent = Clock::now() - begin;
if ( time_spent &lt; min_duration )
{
    std::this_thread::sleep_for( min_duration - time_spent );
}


I find this clearer and easier to understand.

Consider using std::chrono::high_resolution_clock as your default clock type

This stack overflow question should tell you why that's the preferred clock type for timing function execution.

template &lt;typename TimeUnit, typename Clock = std::chrono::high_resolution_clock&gt;
class time_sink;


Concise usage with the std::chrono_literals namespace and a template function

This would simply make the code shorter. Note that there is a repetition, as we must define time_sink's time unit type.

using namespace std::chrono_literals;
using time_sink = time_sink&lt;std::chrono::milliseconds&gt;;
time_sink{ 500ms };


In order to make usage fully concise (avoid repetition), we can use a template function and implement the idea proposed by 5gon12eder, in this comment which simply creates the time_sink object and uses template function type deduction to fill in the details.

template &lt;typename TimeUnit, typename Clock = std::chrono::high_resolution_clock&gt;
time_sink&lt;TimeUnit, Clock&gt; make_time_sink( TimeUnit const minimum_duration )
{
    return time_sink&lt;TimeUnit, Clock&gt;{ minimum_duration };
}


This allows us to create a time_sink in a short and clear way:

using namespace std::chrono_literals;
make_time_sink( 500ms );
// rest of function code, etc.


The improved code

Here's what the final code could look like:

#include &lt;chrono&gt;
#include &lt;thread&gt;

template &lt;typename TimeUnit, typename Clock = std::chrono::high_resolution_clock&gt;
class time_sink
{
public:
    time_sink( TimeUnit const minimum_duration ) :
        min_duration{ minimum_duration },
        begin{ Clock::now() }
    {}

    ~time_sink()
    {
        auto time_spent = Clock::now() - begin;
        if ( time_spent &lt; min_duration )
        {
            std::this_thread::sleep_for( min_duration - time_spent );
        }
    }

private:
    TimeUnit min_duration;
    std::chrono::time_point&lt;Clock&gt; begin;
};

template &lt;typename TimeUnit, typename Clock = std::chrono::high_resolution_clock&gt;
time_sink&lt;TimeUnit, Clock&gt; make_time_sink( TimeUnit const minimum_duration )
{
    return time_sink&lt;TimeUnit, Clock&gt;{ minimum_duration };
}


Sample usage

As 5gon12eder points out, you must also ensure that you keep the return of make_time_sink in order to prevent time_sink's destructor from running early, since destructors are called at the "end of the full expression, for nameless temporaries" (source).

void f()
{
    using namespace std::chrono_literals;

    // we keep the return of make_time_sink in order to prevent
    // time_sink's destructor from executing before the end of the function
    auto ts = make_time_sink( 500ms );
    // ... do work ...
}

int main()
{
    f();
}