Tuesday, October 25, 2011

range size_cast

The range library proposal for the std library included size which calculated the distance between begin(r) and end(r). This value usually ends up in a ptrdiff_t. I often need to put the size of a range into much smaller size types when using C APIs and C structs. Just adding a static_cast is no sufficient as I not only want to cast the type, but ensure that the value fits.

I added size_cast. It requires an explicit ReturnType template parameter. Then it can verify that the value will fit and only then do a static_cast to coerce the value into the ResultType.

The next post will demonstrate some usage.

Implementation

maintained here

template< class ResultType, class InputType >
ResultType
size_cast(InputType size)
{
  const static size_t
  bitsOfPositiveRepresentationInResultType =
    (sizeof(ResultType) * 8) -
    static_cast<ResultType>(
        std::is_signed<ResultType>::value);
  const static size_t
  bitsOfPositiveRepresentationInInputType =
    (sizeof(InputType) * 8) -
    static_cast<InputType>(
        std::is_signed<InputType>::value);
  typedef
  std::conditional <
  bitsOfPositiveRepresentationInResultType <
  bitsOfPositiveRepresentationInInputType,
  InputType,
  ResultType
  >::type
  check_type;
  check_type size_check = static_cast<check_type>(size);
  FAIL_FAST_IF(
    (false,
      (std::is_signed<InputType>::value && size < 0)) ||
        (size_check >> (
          bitsOfPositiveRepresentationInResultType - 1)) != 0,
    ERROR_INVALID_PARAMETER
  );
  return static_cast<ResultType>(size);
}

No comments:

Post a Comment