【问题标题】:template function roundTo int, float -> truncation模板函数 roundTo int, float -> truncation
【发布时间】:2010-05-14 14:32:17
【问题描述】:

根据这个问题: Calling template function without <>; type inference 我将在未来使用的圆形函数现在看起来像:

template < typename TOut, typename TIn >
TOut roundTo( TIn value ) {
   return static_cast<TOut>( value + 0.5 );
}
   double d = 1.54;
   int i = rountTo<int>(d);

但是,只有将它用于舍入到整数数据类型(如 char、short、int、long、long long int 以及它是无符号对应物)时才有意义。 如果它将与 TOut As float 或 long double 一起使用,它将提供 s***。

double d = 1.54;
float f = roundTo<float>(d);
// aarrrgh now float is 2.04;

我正在考虑函数的指定重载,但是 ...
这是不可能的...
你会如何解决这个问题?
非常感谢提前
哎呀

【问题讨论】:

  • 负数呢?例如对于-1.54,您的函数会向上取整到-1,而不是向下取整到-2? (如果您实施了 Alex Martelli 的修复)
  • @Jacob 你说的没错,这是函数的下一个问题

标签: c++ templates function return


【解决方案1】:

假设您想要最接近的整数值,请转换为TOut

static_cast<TOut>( static_cast<long long>(value + 0.5) );

floor 也应该作为内部演员表的替代品。关键是不要依赖转换为未知类型来执行任何截断 - 明确确保截断,使用 floorcast 到众所周知的整数类型,然后执行您需要返回指定类型的进一步转换。

【讨论】:

  • 我真的建议使用floor(),因为使用转换为long long 会导致大数字出现未定义的行为。
  • @jpalecek,因为 OP 意味着使用charshortint 作为TOut 的典型值,所以中间转换为long long 不能再做比最终施放的伤害,例如,short 之后不可避免地会造成伤害。当然,floor 也可以,但是中间转换可能会在微观上更快(当然需要在您的特定编译器和平台上进行测量)。
  • 我也提到了 TOut As long long int。
  • @Oops,当然,但我的意思是,如果 TOut 是任何小于或等于 long long 的整数类型,则嵌套静态转换不会受到伤害(如果您的 C++ 编译器的整数类型更长当然,你可以使用嵌套静态演员中最长的演员)。
【解决方案2】:

您可以禁用非整数返回类型的函数:

#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

template < typename TOut, typename TIn >
typename boost::enable_if<boost::is_integral<TOut>, TOut>::type roundTo( TIn value ) {
   return static_cast<TOut>( value + 0.5 );
}

【讨论】:

  • 正确选择floorceil 的实用程序不是很方便吗?
【解决方案3】:

尝试使用地板:

template < typename TOut, typename TIn >
TOut roundTo( TIn value ) {
   return static_cast<TOut>(floor( value + 0.5 ));
}

double d = 1.54;
int i = rountTo<int>(d);
double d = 1.54;
float f = roundTo<float>(d);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多