4
\$\begingroup\$

Because std doesn't provide an overloaded version of std::abs for std::size_t, I built a version to calculate distance between unsigned numbers.

It subtracts the smaller one from the larger one, to prevent a negative result, since in unsigned integer it would wrap around.

std::size_t size_type_abs(std::size_t a, std::size_t b)
{
    return std::max(a, b) - std::min(a, b);
}

Is this implementation correct and efficient?

\$\endgroup\$
5
\$\begingroup\$

This function computes absolute difference, not absolute value, so it shouldn't be called abs. absolute_difference? size_diff?

What will you use this function for? Are you using size_t for something other than sizes, so an absolute difference is meaningful?

std::max(a, b) - std::min(a, b) is harder to read than a simple conditional:

return a > b ? a - b : b - a;

This function isn't specific to size_t; it can be defined for any type that supports comparison and subtraction:

template<typename T>
T abs_diff(T a, T b) {
  return a > b ? a - b : b - a;
}

If you do want to define it only for size_t, using std::size_t would save some repetitions of std::.

\$\endgroup\$
  • \$\begingroup\$ "std::max(a, b) - std::min(a, b) is harder to read than a simple conditional" seems false to me. For example its much easier to see the difference between std::max(a, b) - std::min(a, b) and std::min(a, b) - std::max(a, b) than between a > b ? a - b : b - a and a > b ? b - a : a - b, or b > a ? a - b : b - a, or b > a ? b - a : a - b. \$\endgroup\$ – bames53 Jul 16 '17 at 3:44
4
\$\begingroup\$

This probably isn't the most efficient method possible. In particular std::min and std::max are typically implemented something like:

template <class T>
T std::min(T a, T b) { return a < b ? a : b; }

template <class T>
T std::max(T a, T b) { return a < b ? b : a; }

So, the overall code looks something like this:

std::size_t size_type_abs(std::size_t a, std::size_t b) { 
    return a < b ? a : b - a < b ? b : a;
}

The compiler may (but certainly won't necessarily) recognize that one of these comparisons is redundant. I'd prefer to ensure that only one comparison is done:

std::size_t size_type_abs(std::size_t a, std::size_t b) { 
   return a < b ? b - a : a - b;
}

This might be about the same efficiency as your version, or it might be marginally better. I'd be rather surprised to see it any less efficient though. I see little difference in readability between the two, so no real preference on that account.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.