Home > front end >  Is it discouraged to overload STL functions?
Is it discouraged to overload STL functions?

Time:04-15

I was wondering if it is discouraged to overload an STL function, and if so, why?

I ran across an issue yesterday, where I found that std::fpclassify doesn't have an integral overload on microsoft compilers (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fpclassify?view=msvc-170) as it does for other compilers (see (4) in https://en.cppreference.com/w/cpp/numeric/math/fpclassify).

I ran across this issue when I tried to compile

T var; // T can be an integral type
std::isnan(var); // 

using microsoft C compiler.

I already have a working solution to solve this issue that didn't involve overloading std::fpclassify, but I did consider maybe just writing an overload for std::fpclassify myself, but it seems it would have gotten hairy because the code might be compiled using non-microsoft compilers, in which case, we would already have the integral overload defined.

CodePudding user response:

Is it discouraged to overload STL functions?

You aren't allowed to add any overloads into the std namespace. It's fine to add overloads into custom namespaces.

and if so, why?

Because the standard says so. Probably so that your program won't break when the standard (implementation) changes.

CodePudding user response:

No. There is no issue as long as you are not trying to place your custom overload inside the namespace std, because that is undefined except in some cases.

Consider std::swap where you are even encouraged to provide an overload when swapping two objects should do something that std::swap cannot do:

#include <iostream>
#include <algorithm>

namespace X {

struct foo {
    int value;
    bool operator<(const foo& other) { return value < other.value; }
};

void swap(foo& a, foo& b) noexcept {
    std::cout << "swap\n";
    std::swap(a.value,b.value);
}

}

int main() {
    std::vector<X::foo> v{{2},{1}};
    std::iter_swap(v.begin(),v.begin() 1);   // calls X::swap
    std::cout << v[0].value << " " << v[1].value << "\n";

    std::vector<int> w{2,1};
    std::iter_swap(w.begin(),w.begin() 1);  // calls std::swap
    std::cout << w[0] << " " << w[1];
}

Output:

swap
1 2
1 2

This relies on ADL, which means it wont work for fundamental types or types from std. Only if you wrap them inside a custom class inside some namespace like above you can use it for int and the like.

  • Related