C++ 有没有办法阻止开发人员使用std::min、std::max?
我们有一个算法库,对可能是NaN的数字执行大量的C++ 有没有办法阻止开发人员使用std::min、std::max?,c++,C++,我们有一个算法库,对可能是NaN的数字执行大量的std::min/std::max操作。考虑到这篇文章,我们意识到这显然是不安全的 有没有办法阻止开发人员使用std::min/std::max 我们的代码是用VS2015和g++编译的。我们的所有源文件都包含一个通用头文件(通过VS2015的/FI选项和g++的-include)。是否有任何代码/pragma可以放在这里,使任何cpp文件使用std::min或std::max编译失败 顺便说一句,像使用此函数的STL头这样的遗留代码不应该受到影响
std::min
/std::max
操作。考虑到这篇文章,我们意识到这显然是不安全的
有没有办法阻止开发人员使用std::min
/std::max
我们的代码是用VS2015和g++编译的。我们的所有源文件都包含一个通用头文件(通过VS2015的/FI
选项和g++的-include
)。是否有任何代码/pragma可以放在这里,使任何cpp文件使用std::min
或std::max
编译失败
顺便说一句,像使用此函数的STL头这样的遗留代码不应该受到影响。只有我们编写的代码应该受到影响。没有可移植的方法来做到这一点,因为除了几个例外,您不允许在std
中更改任何内容
然而,一个解决办法是
#定义max foo
在包含任何代码之前。然后std::max
和max
都会出现编译时故障
但实际上,如果我是你,我会习惯你平台上的
std::max
和std::min
行为。如果他们没有按照标准要求去做,那么就向编译器供应商提交一份bug报告。我认为让标准库函数不可用不是正确的方法。首先,NaN是浮点值工作原理的一个基本方面。您需要禁用所有其他功能,例如,sort()
,下限()
,等等。此外,程序员因创造性而获得报酬,我怀疑任何想要使用std::max()
的程序员都会犹豫使用a
如果std::max(a,b)不起作用
此外,您显然不希望对没有NaN的类型(例如整数或字符串)禁用std::max()
或std::min()
。所以,你需要一个有点控制的方法
没有可移植的方法来禁用命名空间std
中的任何标准库算法。您可以通过提供适当的delete
d重载来定位这些算法的使用,例如:
namespace std {
float max(float, float) = delete; // **NOT** portable
double max(double, double) = delete; // **NOT** portable
long double max(long double, long double) = delete; // **NOT** portable
// likewise and also not portable for min
}
这里我要讲一点哲学,少讲代码。但我认为最好的方法是教育这些开发人员,并解释为什么他们不应该以特定的方式编写代码。如果你能给他们一个很好的解释,那么他们不仅会停止使用你不希望他们使用的函数。他们将能够将信息传播给团队中的其他开发人员
我相信强迫他们只会让他们想出解决办法。您不赞成使用std::min std::max。您可以通过使用grep进行搜索来找到实例。或者,您可以随意处理标题本身,以中断std::min,std::max。或者您可以尝试为预处理器定义min/max或std::min,std::max。后者由于C++命名空间有点狡猾,如果您定义了STD::Max/min,则不使用命名空间STD,如果定义MI/MAX,也会获取这些标识符的其他用法。
#pragma GCC poison min max atoi /* etc ... */
或者,如果项目有一个每个人都包含的标准标题,如“mylibrary.lib”,则在其中断开std::min/max
当然,当传递NaN时,函数应该返回NaN。但是写它们的自然方式总是会触发错误。因为修改
std
是不允许的,下面是UB,但在您的情况下可能会起作用。
将函数标记为已弃用:
自c++14以来,不推荐使用的属性:
namespace std
{
template <typename T>
[[deprecated("To avoid to use Nan")]] constexpr const T& (min(const T&, const T&));
template <typename T>
[[deprecated("To avoid to use Nan")]] constexpr const T& (max(const T&, const T&));
}
名称空间std
{
模板
[[已弃用(“避免使用Nan”)]]constexpr const T&(min(const T&,const T&));
模板
[[已弃用(“避免使用Nan”)]]constexpr const T&(max(const T&,const T&));
}
之前
#ifdef __GNUC__
# define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
# define DEPRECATED(func) __declspec(deprecated) func
#else
# pragma message("WARNING: You need to implement DEPRECATED for this compiler")
# define DEPRECATED(func) func
#endif
namespace std
{
template <typename T> constexpr const T& DEPRECATED(min(const T&, const T&));
template <typename T> constexpr const T& DEPRECATED(max(const T&, const T&));
}
\ifdef\uu GNUC__
#定义不推荐的(func)func ____((不推荐))
#elif已定义(\u MSC\u VER)
#定义已弃用(func)\定义已弃用(func)
#否则
#pragma消息(“警告:您需要为此编译器实现弃用”)
#定义不推荐使用的(func)func
#恩迪夫
名称空间标准
{
模板constexpr const T&已弃用(最小值(const T&,const T&));
模板constexpr const T&已弃用(最大值(const T&,const T&));
}
我不打算准确地回答你的问题,但你可以教育你的同事,确保你一直使用总订单比较器,而不是原始的
运算符std::min
和std::max
无论何时使用依赖于给定订单的函数。/p
pSuch a比较器是为标准化而提出的(以及部分和弱阶比较器),可能以C++20为目标。与此同时,C标准委员会已经在这方面工作了相当长的一段时间,显然是针对未来的C2x(应该是~C23),它用许多新函数更新了codemath.h/code头,以实现最近的版本。在新函数中,有codetotalorder/code(第14.8节),它根据IEEE codetotalorder/code:/p比较浮点数
块引用
ptotalOrder(emx/em,emy/em)对emx/em和emy/em格式的规范成员施加总排序:/p
ol
li如果emx/em- 如果x和y有负号,则totalOrder(x,y)为真当且仅当x的指数为≥ y的指数
- 否则totalOrder(x,y)为真当且仅当x的指数为≤ y的指数
error: attempt to use poisoned "min"
#define strrchr rindex
#pragma GCC poison rindex
strrchr(some_string, 'h');