我正在使用一个C库,该库使用无符号整数作为某些数据的索引。但是有时,如果函数未能返回索引,则函数会返回这些带符号的索引,以便返回-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
}
答案 0 :(得分: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);
}
如果您不喜欢为此类琐碎的事情引发异常,还可以返回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);
}
答案 1 :(得分:4)
如果您希望在运行时进行范围检查(即允许在 iff 类型之间进行转换,则可以保持所保存的值),Boost具有numeric_cast
来实现。
如果您不想使用Boost,那么您的方法看起来还不错。
答案 2 :(得分:-1)
编辑:我想念您使用的是C ++,我以前的回答仅假定为C。
最简单,最标准的方法是使用
std::optional<unsigned int> index;
而不是使用-1或其他一些前哨值来表示无效索引。如果索引无效,则无需设置可选参数。然后您可以使用
进行查询index.has_value()
找出它是否有效。