Join the Stack Overflow Community
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

We have an algorithm library doing lots of std::min/std::max operations on numbers that could be NaN. Considering this post: Why does Release/Debug have a different result for std::min?, we realised it's clearly unsafe.

Is there a way to prevent developers from using std::min/std::max?

Our code is compiled both with VS2015 and g++. We have a common header file included by all our source files (through /FI option for VS2015 and -include for g++). Is there any piece of code/pragma that could be put here to make any cpp file using std::min or std::max fail to compile?

By the way, legacy code like STL headers using this function should not be impacted. Only the code we write should be impacted.

share|improve this question
    
Even if it is UB (as the function are in std), you can mark the function as deprecated. – Jarod42 1 hour ago
3  
I guess your approach is understandable but not optimal: Using NaN in arithmetic operations, i.e. for more than just a flag/result is a fault in your design. I would either check in the algorithms, use a own NaN, try to prevent using it or redesign the library. But prevent developers from using standard library tools is born to fail and IMHO riding a dead horse. – Superlokkus 1 hour ago
    
@Jarod42: How do you do that? – jpo38 1 hour ago
    
@jpo38: Look at c-mark-as-deprecated – Jarod42 1 hour ago
    
@Jarod42: Saw that, but could not make it work with a template function being in a namespace (like std::min). – jpo38 1 hour ago
up vote 5 down vote accepted

I don't think making standard library functions unavailable is the correct approach. First off, NaN are a fundamental aspect of how floating point value work. You'd need to disable all kinds of other things, e.g., sort(), lower_bound(), etc. Also, programmers are paid for being creative and I doubt that any programmer reaching for std::max() would hesitate to use a < b? b: a if std::max(a, b) doesn't work.

Also, you clearly don't want to disable std::max() or std::min() for types which don't have NaN, e.g., integers or strings. So, you'd need a somewhat controlled approach.

There is no portable way to disable any of the standard library algorithms in namespace std. You could hack it by providing suitable deleted overloads to locate uses of these algorithms, e.g.:

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
}
share|improve this answer
    
This delete trick works perfectly, at least for VS compiler. std::min/std::max can't be used anymore! Not sure I'll use it in the end (as commented by many, it's probably better to avoid comparing NaN to non-NaN anyway). – jpo38 1 hour ago
    
This is pretty much relying on undefined behaviour though. – Gill Bates 1 hour ago
    
@Bathsheba: I don't know what you mean: = delete can be used to delete any overload. It works both at class as well as namespace scope. There is no constraint in 8.4.3 [dcl.fct.def.delete] limiting its use to member functions. It is just a special form of function body. – Dietmar Kühl 53 mins ago
    
may I inquire why it's not portable? – sfk92fksdf 15 mins ago
    
@sfk92fksdf: due to 17.6.4.2.1 [namespace.std] paragraph 1: "The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. ..." There isn't a specification allowing overloads. The basic reason is simply that the standard library may use these functions and having user code use a different definition is a violation of the One Definition rule. – Dietmar Kühl 11 mins ago

There's no portable way of doing this since, aside from a couple of exceptions, you are not allowed to change anything in std.

However, one solution is to

#define max foo

before including any of your code. Then both std::max and max will issue compile-time failures.

But really, if I were you, I'd just get used to the behaviour of std::max and std::min on your platform. If they don't do what the standard says they ought to do, then submit a bug report to the compiler vendor.

share|improve this answer
    
Tried the macro definition. But it has too much side effects. Like std::numeric_limits<T>::max() not being allowed anymore... – jpo38 1 hour ago
    
I'm not sure if it is a compiler bug. If min/max where one is a NaN has no defined result then it doesn't matter what gets returned. – CashCow 1 hour ago
    
@GillBates: Unfortunately : are not permitted in macro names (at least for VS, it reports error C2008: ':': unexpected in macro definition) – jpo38 1 hour ago

I'm going bit philosophical hear and less code. But I think the best approach would be to educate those developers, and explain why they shouldn't code in a specific way. If you'll be able to give them a good explanation not only they'll stop using functions that you don't want them to. They will be able to spread the message to other developers in the team.

I believe that forcing them will just make them come up with work arounds.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.