Home > Software engineering >  Unqualified lookup of operators in standard library templates
Unqualified lookup of operators in standard library templates

Time:03-06

namespace N {
    struct A {};
    
    template<typename T>
    constexpr bool operator<(const T&, const T&) { return true; }
}

constexpr bool operator<(const N::A&, const N::A&) { return false; }

#include<functional>

int main() {
    static_assert(std::less<N::A>{}({}, {}), "assertion failed");
}

See https://godbolt.org/z/vsd3qfch6.

This program compiles on seemingly random versions of compilers.

The assertion fails on all versions of MSVC since v19.15, but succeeds on v19.14.

It succeeds on GCC 11.2 and before, but fails on current GCC trunk.

It fails on Clang with libstdc in all versions. It succeeds with libc in all versions, including current trunk, except version 13.

It always succeeds with ICC.


Is it specified whether or not the static_assert should succeed?


The underlying issue here is that std::less uses < internally, which because it is used in a template will find operator< overloads via argument-dependent lookup from the point of instantiation (which is the proper method), but also via unqualified name lookup from the point of definition of the template.

If the global overload is found, it is a better match. Unfortunately this make the program behavior dependent on the placement and order of the standard library includes.

I would have expected that the standard library disables unqualified name lookup outside the std namespace, since it cannot be relied on anyway, but is that supposed to be guaranteed?

CodePudding user response:

What matters here is whether the unqualified lookup from inside std finds any other operator< (regardless of its signature!) before reaching the global namespace. That depends on what headers have been included (any standard library header may include any other), and it also depends on the language version since C 20 replaced many such operators with operator<=>. Also, occasionally such things are respecified as hidden friends that are not found by unqualified lookup. It’s obviously unwise to rely on it in any case.

  • Related