C++ 表达模板化数值文字的最佳方式是什么?
我有一个函数,可以简化成这样:C++ 表达模板化数值文字的最佳方式是什么?,c++,templates,c++11,type-conversion,literals,C++,Templates,C++11,Type Conversion,Literals,我有一个函数,可以简化成这样: template<class T> T foo(T x) { return 123.45 / x; } 模板 T foo(T x) { 返回123.45/x; } 我想确保数字文字123.45与x的类型相同。假设T可以是任何数字类型:有符号/无符号字符到long long或float到long double 用什么最现代的方式表明123.45应为T型 我的要求 不应发出任何警告(打开每个警告) 我希望十进制数123.45在计算中使用时具有T的
template<class T>
T foo(T x)
{
return 123.45 / x;
}
模板
T foo(T x)
{
返回123.45/x;
}
我想确保数字文字123.45与x的类型相同。假设T可以是任何数字类型:有符号/无符号字符到long long或float到long double
用什么最现代的方式表明123.45应为T型 我的要求
- 不应发出任何警告(打开每个警告)
- 我希望十进制数123.45在计算中使用时具有T的精度
- 我想要实现这些目标的最优雅的解决方案
- “旧式CAST”,即<代码>(t)123.45 < /C>基本上是用C++来表示的。
似乎是正确的类型。然而,它是冗长的,我从来没有见过在文字上使用它static\u cast(123.45)
- 我不确定在T为长双精度的情况下,是否需要后缀(例如,
)来获得最大精度,或者编译器是否会自动使用精度最高的十进制到二进制转换123.45L
在将代码库中的数百个强制转换更改为
T(123.45)
形式后,我发现有时这种语法不可用。例如,您不能做<代码> long double(123.45)< /COD>,因为C++不支持多令牌类型的构造函数。在这些情况下,我选择了static\u cast(123.45)
static\u cast
是一种选择。这就是C类型转换所等价的,在任何保留原始含义但改变值类型的转换中
如果是具有数字特征的类类型,static\u cast
将调用一个单参数构造函数,甚至是一个explicit
one
如果要避免缩小转换范围,可以使用语法
T{123.45}
。这不像C样式转换,而是使用直接列表初始化。它仍然允许显式构造函数,但对其参数类型的任何数字转换都必须精确。(不允许溢出或舍入。对于文本,此约束针对特定值进行检查,而不是作为类型之间的关系。但是,当我将12.0
传递给int
时,GCC会发出警告;我不确定这是否正确。)静态强制转换是自然的。如果你还没有看到它,那么,并不是每个人都能看到发生的一切:-)我倾向于使用C风格的类型转换,当(a)我知道这两种类型时,(b)我有权有点懒惰。正如您将在下面的代码中看到的
如果希望在T
比double
更精确时获得精度,则确实需要L
后缀。潜在static_cast(123.45)!=123.45升
假设T
是某种更精确的类型,比如GMP中的mpf\u类
,或者是long double
之外的某种特定于编译器的扩展类型。您可能需要考虑<代码> Boo::ListalyCost(“123.45”)< /代码>。当然,这对整数类型不起作用,您需要两个单独的案例,分别使用enable\u if
或其他什么
还要注意,如果T
是一个比int
低秩的整数类型,那么例如short(123.45)/x
与int(123.45)/x
相同,因为除法是以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/(无符号字符)2!=(无符号字符)-1/(无符号字符)2
[*]我忽略了
bool
,实际上我不记得它是否是数字类型。您也可以尝试以下方法:
// 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;
}
//realcontent.h
模板
类实常数
{
公众:
静止的
常量真实值;
};
#定义实数\常数\声明(实数)\
模板\
常量实实常量::值;
实常量声明(浮点)
实数常量声明(双精度)
实数常量声明(长双精度)
#未定义实数常量声明
//RealConstant.cpp
#包括“realcontent.h”
#定义实数\常数\定义(实数、常量值)\
模板\
const Real realcontent::value=constantValue;
实常数定义(浮点,123.45f)
实常数定义(双精度,123.45)
实常数定义(长双精度,123.45L)
#未定义实常数定义
//在其中定义“foo”函数模板的文件
#包括“realcontent.h”
模板
T foo(T x)
{
返回realcontent::value/x;
}
当然,实际上并不需要宏。我将从文本中初始化常量
T
:
template<class T>
T foo(T x)
{
const T magic = 123.45;
return magic / x;
}
模板
T foo(T x)
{
常数T魔法=123.45;
返回魔法/x;
}
它同时比static\u cast
更明确、可读性更强,更重要的是,它让您有机会用适当的名称记录魔法数字;) 一个简单的
template<class T>
T foo(T x)
{
return T(123.45) / x;
}
模板
T foo(T x)
{
返回T(123.45)/x;
}
这将允许自定义数字类接受构造函数中的值。“指出123.45应为T类型的最现代方式是什么?”将
T
替换为double
@juanchopanza:基于long double
与“现代”体系结构上的double
具有相同的精度,你是说?@SteveJessop基于