我有一个可以简化为这样的功能:
template<class T>
T foo(T x)
{
return 123.45 / x;
}
我想确保数字文字123.45与x的类型相同。假设T可以是任何数字类型:signed / unsigned char to long-long或float to long-double。
表明123.45应该是T型的最现代的方法是什么?
我的要求
正在考虑的问题
(T)123.45
在C ++中基本上已被弃用。static_cast<T>(123.45)
似乎是正确的演员类型。但是,它很冗长,我从来没有在文字中看到过这种情况。123.45L
)以便在T为long double
的情况下获得最大精度,或者编译器是否会自动使用最高精度小数 - 到二进制转换。更新5-7-2014
在我的代码库中将数百个强制转换更改为T(123.45)
形式后,我发现有时这种语法不可用。例如,您不能执行long double(123.45)
,因为C ++不支持多字节类型构造函数。在这些情况下,我选择了static_cast<long double>(123.45)
。
答案 0 :(得分:3)
static_cast
是要走的路。这就是C cast等同于任何保留原始含义但会改变值类型的转换。
如果它是具有数字特征的类类型,static_cast
将调用单参数构造函数,甚至是explicit
构造函数。
如果您想避免缩小转化次数,可以使用语法T{ 123.45 }
。这不像C风格的强制转换,但使用直接列表初始化。它仍然允许explicit
构造函数,但是对其参数类型的任何数值转换都必须精确。 (不允许溢出或舍入。对于文字,检查特定值的约束,而不是类型之间的关系。但是,当我将12.0
传递给int
时,GCC会发出警告;我不是确定是否正确。)
答案 1 :(得分:3)
静态演员是自然的。如果你还没有看到它,那么,不是每个人都能看到发生的一切:-)我倾向于使用C风格的演员表(a)我知道两种类型都涉及,(b)我有权懒得。正如您将在下面的代码中看到的那样。
如果您想要L
比T
更精确的精度, 需要double
后缀。潜在的static_cast<long double>(123.45) != 123.45L
。
假设T
是一些更精确的类型,例如来自GMP的mpf_class
或超出long double
的某些特定于编译器的扩展类型。您可能需要考虑boost::lexical_cast<T>("123.45")
。当然,这对整数类型不起作用,你需要两个单独的enable_if
或其他案例。
另请注意,如果T
是排名低于int
的整数类型,则例如short(123.45) / x
与int(123.45) / x
相同,因为除法在{ {1}}无论哪种方式和int
。如果short(123.45) == int(123.45)
是比T
更高级别的整数类型,那么例如int
仍然与long(123.45) / x
相同,因为该分部将是以任意方式int(123.45) / x
和T
执行。此分析依赖于int(123.45) == long(123.45)
在任何整数类型[*]中具有相同值的事实。如果您可以将123
转换为123.45
,那么事情可能会有所不同。例如T
。
[*]我忽略了-1 / (unsigned char)2 != (unsigned char)-1 / (unsigned char)2
,我实际上无法记住它是否是数字类型。
答案 2 :(得分:3)
一个简单的
template<class T>
T foo(T x)
{
return T(123.45) / x;
}
允许自定义数字类接受构造函数中的值。
答案 3 :(得分:1)
您也可以尝试以下列方式执行此操作:
// RealConstant.h
template <typename Real>
class RealConstant
{
public:
static
const Real value;
};
#define REAL_CONSTANT_DECLARATION(Real) \
template <> \
const Real RealConstant<Real>::value;
REAL_CONSTANT_DECLARATION(float)
REAL_CONSTANT_DECLARATION(double)
REAL_CONSTANT_DECLARATION(long double)
#undef REAL_CONSTANT_DECLARATION
// RealConstant.cpp
#include "RealConstant.h"
#define REAL_CONSTANT_DEFINITION(Real, constantValue) \
template <> \
const Real RealConstant<Real>::value = constantValue;
REAL_CONSTANT_DEFINITION(float, 123.45f)
REAL_CONSTANT_DEFINITION(double, 123.45)
REAL_CONSTANT_DEFINITION(long double, 123.45L)
#undef REAL_CONSTANT_DEFINTION
// File in which `foo` function template is defined
#include "RealConstant.h"
template<class T>
T foo(T x)
{
return RealConstant<T>::value / x;
}
当然不需要宏。
答案 4 :(得分:0)
我会从文字中初始化一个常量T
:
template<class T>
T foo(T x)
{
const T magic = 123.45;
return magic / x;
}
它同时比static_cast
更明确,更易读,更重要的是让您有机会用正确的名称记录幻数;)