正确施放签名到未签名

Gam*_*ion 3 c++

我正在使用一个C库,它使用无符号整数作为某些数据的索引.但有时,函数会将这些索引返回为signed,以便-1在函数无法返回索引时返回.*

implicit conversion changes signedness如果无法进行转换,如何防止警告,而是抛出运行时错误?您是否建议将库函数包装为使用异常进行错误处理并仅返回正确的值?有没有标准的方法来做到这一点:

#include <stdlib.h>
#include <errno.h>
#include <limits.h>

// pointless c function to demonstrate the question
// parse the string to an unsigned integer, return -1 on failure
int atoui(char const* str) {
    char* pend;
    long int li=strtol(str, &pend, 10);
    if ( errno!=0 || *pend!='\0' || li<0 || li>INT_MAX ) {
        return -1;
    } else {
        return li;
    }
}

// --8<---

#include <stdexcept>

// How to do this properly?
unsigned int unsign(int i) {
    if(i<0) {
        throw std::runtime_error("Tried to cast negative int to unsigned int");
    } else {
        return static_cast<unsigned>(i);
    }
}

int main() {
    unsigned int j=unsign(atoui("42")); // OK
    unsigned int k=unsign(atoui("-7")); // Runtime error
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 6

标准库没有这样的功能,但编写这样的模板很容易:

template<typename SInt, typename = std::enable_if_t<std::is_integeral_v<SInt> && std::is_signed_v<SInt>>>
constexpr auto unsigned_cast(Sint i)
{
  if(i < 0) throw std::domain_error("Outside of domain");
  return static_cast<std::make_unsigned_t<SInt>>(i);
}
Run Code Online (Sandbox Code Playgroud)

optional如果你不喜欢为这些微不足道的事情抛出异常,你也可以返回:

template<typename SInt, typename = std::enable_if_t<std::is_integeral_v<SInt> && std::is_signed_v<SInt>>>
constexpr std::optional<std::make_unsigned_t<SInt>> unsigned_cast_opt(Sint i)
{
  if(i < 0) return std::nullopt;
  return static_cast<std::make_unsigned_t<SInt>>(i);
}
Run Code Online (Sandbox Code Playgroud)


Lig*_*ica 5

如果您想在运行时进行范围检查(即,如果可以维护所持有的值,则允许类型之间的转换),Boostnumeric_cast可以实现这一点。

如果您不想使用 Boost,您的方法看起来还不错。