c++stlargument-dependent-lookup

Best practice for overloading functions with only STL types


I would like to overload operator<<(std::ostream&, std::chrono::duration<std::uint64, std::nano>) - and ideally without requiring users to write using statements everywhere.

What's the best practice here?


Context...

// Replace code like this:
using Time = std::uint64_t;
void example(Time ts) {
    if (ts) { std::cout << ts; }

}

// with code like this:
using Time = std::chrono::duration<std::uint64_t, std::nano>;
void example(Time ts) {
    if (!!ts) { std::cout << ts; }
}

// this 'works for me'; but it is not allowed to add overloads to `namespace std`
// The type `Time` can be used in any other namespace, and the operators are found by ADL
namespace std {
    ostream& operator<<(ostream&, chrono::duration<uint64_t, nano>);
    bool operator!(chrono::duration<uint64_t, nano>);
}

Is there a way to get the effect of placing the overloads in the std namespace without breaking the rules on extending namespace std?


Solution

  • You put it in the global namespace. Any function outside of namespace std that does name lookup for << will find your overload, and prefer it to the one defined in C++20.

    Afaict, the only place where this fails is std::ostream_iterator, as that is the only call to << within namespace std.

    See it on coliru