是否可以将 std::numeric_limits 专门<T>用于用户定义的类数字类?
is it ok to specialize std::numeric_limits<T> for user-defined number-like classes?
std::numeric_limits<T>
的文档说它不应该专门用于非基本类型。那么类似数字的用户定义类型呢?如果我定义了自己的类型T
,它表示一个数值并重载数值运算符,并且numeric_limits
表示的信息对它有意义——如果我将numeric_limits
专一化为该类型,会有什么破坏吗?
简短回答:
去吧,不会发生坏事的。
长答:
c++标准在c++ 11 17.6.4.2.1中广泛地保护::std
命名空间,但在第1段和第2段中特别允许您的情况:
c++程序的行为是未定义的,如果它将声明或定义添加到命名空间std或命名空间STD中的命名空间,除非另有指定。程序可以添加模板专门化对于任何标准库模板,仅当声明依赖于用户定义类型时,才将其命名为STD并且专门化满足原始模板的标准库需求,并且不显式禁止。
[…程序可以显式实例化标准库中定义的模板,只有当声明依赖于用户定义类型的名称,并且实例化满足标准库要求
旧的c++ 03在17.4.3.1/1中有类似的定义:
c++程序向命名空间std或命名空间添加声明或定义是未定义的在命名空间STD内,除非另有指定。程序可以为任何对象添加模板专门化标准库模板到命名空间std。标准的这种专门化(全部或部分)标准库模板导致未定义的行为,除非声明依赖于的用户定义名称外部链接,除非专门化满足原始模板的标准库要求。
在通过了这个基本的垫脚石之后,您已经指出,c++ 03 18.2.1/4禁止对某些类型的::std::numeric_limits
进行专门化:
非基本标准类型,如complex(26.2.2),不能有专门化。
最新的c++ 11 18.3.2.1/4有一个稍微不同的措辞:
非算术标准类型,如
complex<T>
(26.4.2),不能有专门化。
然而,这两个公式都允许非标准类型的专门化,T
就是,因为你自己定义了它(正如@BoPersson已经在评论中指出的)。
警告
c++ 11 18.3.2.3/1提示你应该(但不要求你)确保你的专门化具有所有成员。
同样,您可能希望确保您的专门化不违反c++ 11 18.3.2.3/2:
cv限定类型cv T上的numeric_limits特化的每个成员的值必须相等到非限定类型t的专门化对应成员的值
这基本上意味着,如果你想为T
专门化它,你也应该为T const
、T volatile
和T const volatile
专门化它。
举个例子:
namespace std {
template<> class numeric_limits<Temperature> {
public:
static Temperature lowest() {return Temperature(-273.15f);};
// One can implement other methods if needed
};
}
- 专用于 std 元组的模板,而无需用户执行remove_cvref
- 用于获取枚举值的用户输入
- 是否可以在运行时调用用于选择要调用的用户定义文本的逻辑?
- 表达式模板玩具示例:用户定义的强制转换不适用于复杂类型
- C++代码,用于在用户插入的字符串的每个元音之后插入一对字符
- 用户定义的转换不适用于可变参数函数参数?为什么不呢?
- 用户指定的参数,用于确定在大循环中调用哪个函数
- 用于在C++中计算用户数据的线程
- 指定在用户固定我的应用程序时用于运行应用程序的命令参数
- C++ 将用户输入数据用于多个函数
- std::sort 不适用于带有 oveload <运算符的用户定义对象
- 如何使用用户输入正确修改 2D 数组中的字符数组元素?专门用于电影院座位
- 用户定义的转换运算符不适用于引用
- 将 std 库函数专门用于用户定义类型的shared_ptr是否合法?
- 拥有用于QT应用程序的Web用户界面的最佳方法
- C 17:始终调用用户定义的构造函数,并且运算符 超载不适用于儿童课程
- 奇怪的用户定义的比较结构错误,用于C++中的priority_queue
- 用户定义的功能用于竞争编程中,以获取输入
- 智能指针的成员初始化列表,用于用户定义的结构
- 用户用于输入程序设置的文件约定