c++ 有等效的 boost::numeric_cast<DestType>(SourceType) 吗?
does c++ have an equivalent boost::numeric_cast<DestType>(SourceType)?
我正在编写一堆 applied-mathematics/signal-processing/algorithms C++ 代码。
我已启用 -Wconversion
编译器警告以捕获诸如类型为 double
的数字运行时转换为类型 int32_t
.
等问题
显然,在这些转换过程中我总是很担心,因为:
- 数字十进制值丢失
- 可能的正溢出或负溢出("positive overflow" 是指双精度值大于 INT32_MAX 并尝试将该值存储在目标类型中(在本例中为
int32_t
) )
每当我担心这种转换时,我通常会使用单行检查:
boost::numeric_cast<DestType>(SourceType)
但是我想在没有 boost
的情况下做同样的事情。
直接 C++ 是否有等效的 boost::numeric_cast<DestType>(SourceType)
?
如果纯 C++ 没有等效项,那么什么是可比较的非 boost
实现?
我认为有点类似的检查基本上是一个模板函数,它有一个 if 语句来检查输入参数是否正溢出或负溢出(通过使用 std::numeric_limits<DestType>
::max()
和 ::min()
并抛出异常)。
,不,标准 C++ 规范目前没有相当于 Boost 的 boost::numeric_cast<typename Destination>(Source value)
.
这是一个仅使用标准 C++ 的 straight-forward 实现:
template<typename Dst, typename Src>
inline Dst numeric_cast(Src value)
{
typedef std::numeric_limits<Dst> DstLim;
typedef std::numeric_limits<Src> SrcLim;
const bool positive_overflow_possible = DstLim::max() < SrcLim::max();
const bool negative_overflow_possible =
SrcLim::is_signed
or
(DstLim::lowest() > SrcLim::lowest());
// unsigned <-- unsigned
if((not DstLim::is_signed) and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// unsigned <-- signed
else if((not DstLim::is_signed) and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
else if(negative_overflow_possible and (value < 0)) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// signed <-- unsigned
else if(DstLim::is_signed and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// signed <-- signed
else if(DstLim::is_signed and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
} else if(negative_overflow_possible and (value < DstLim::lowest())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// limits have been checked, therefore safe to cast
return static_cast<Dst>(value);
}
备注:
- 编译器是 g++ 版本 4.8.5。
- 编译器标志:
- -std=c++0x
- -O0
- -g3
- -迂腐
- -pedantic-errors
- -墙
- -Wextra
- -错误
- -W转换
- -c
- -fmessage-length=0
- -Wsign-conversion
- -fPIC
- -MMD
- -MP
- 对于浮点类型你不能使用
std::numeric_limits<float>::min()
而是必须使用 std::numeric_limits<Dst>::lowest()
因为 ::min
returns 是 1e-38 而不是负浮点值
- 许多
std::numeric_limits
是 const 表达式,因此编译器将能够在编译时大大简化它(即 N if 语句将在编译时减少为一个 if-statement 或 none)
我正在编写一堆 applied-mathematics/signal-processing/algorithms C++ 代码。
我已启用 -Wconversion
编译器警告以捕获诸如类型为 double
的数字运行时转换为类型 int32_t
.
显然,在这些转换过程中我总是很担心,因为:
- 数字十进制值丢失
- 可能的正溢出或负溢出("positive overflow" 是指双精度值大于 INT32_MAX 并尝试将该值存储在目标类型中(在本例中为
int32_t
) )
每当我担心这种转换时,我通常会使用单行检查:
boost::numeric_cast<DestType>(SourceType)
但是我想在没有 boost
的情况下做同样的事情。
直接 C++ 是否有等效的 boost::numeric_cast<DestType>(SourceType)
?
如果纯 C++ 没有等效项,那么什么是可比较的非 boost
实现?
我认为有点类似的检查基本上是一个模板函数,它有一个 if 语句来检查输入参数是否正溢出或负溢出(通过使用 std::numeric_limits<DestType>
::max()
和 ::min()
并抛出异常)。
boost::numeric_cast<typename Destination>(Source value)
.
这是一个仅使用标准 C++ 的 straight-forward 实现:
template<typename Dst, typename Src>
inline Dst numeric_cast(Src value)
{
typedef std::numeric_limits<Dst> DstLim;
typedef std::numeric_limits<Src> SrcLim;
const bool positive_overflow_possible = DstLim::max() < SrcLim::max();
const bool negative_overflow_possible =
SrcLim::is_signed
or
(DstLim::lowest() > SrcLim::lowest());
// unsigned <-- unsigned
if((not DstLim::is_signed) and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// unsigned <-- signed
else if((not DstLim::is_signed) and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
else if(negative_overflow_possible and (value < 0)) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// signed <-- unsigned
else if(DstLim::is_signed and (not SrcLim::is_signed)) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
}
}
// signed <-- signed
else if(DstLim::is_signed and SrcLim::is_signed) {
if(positive_overflow_possible and (value > DstLim::max())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": positive overflow"));
} else if(negative_overflow_possible and (value < DstLim::lowest())) {
throw std::overflow_error(__PRETTY_FUNCTION__ +
std::string(": negative overflow"));
}
}
// limits have been checked, therefore safe to cast
return static_cast<Dst>(value);
}
备注:
- 编译器是 g++ 版本 4.8.5。
- 编译器标志:
- -std=c++0x
- -O0
- -g3
- -迂腐
- -pedantic-errors
- -墙
- -Wextra
- -错误
- -W转换
- -c
- -fmessage-length=0
- -Wsign-conversion
- -fPIC
- -MMD
- -MP
- 对于浮点类型你不能使用
std::numeric_limits<float>::min()
而是必须使用std::numeric_limits<Dst>::lowest()
因为::min
returns 是 1e-38 而不是负浮点值 - 许多
std::numeric_limits
是 const 表达式,因此编译器将能够在编译时大大简化它(即 N if 语句将在编译时减少为一个 if-statement 或 none)