Popular Releases
Popular Libraries
New Libraries
Top Authors
Trending Kits
Trending Discussions
Learning
Release 1.10.0 | |
Release 1.9.1 | |
v2.0.0 | |
3.7.0 |
assert Release 1.10.0 |
assert Release 1.9.1 |
jest-extended v2.0.0 |
shouldly |
sinon-chai 3.7.0 |
1
7 Libraries
1030
2
7 Libraries
70
3
5 Libraries
2288
4
4 Libraries
2817
5
4 Libraries
48
6
3 Libraries
18
7
3 Libraries
17
8
3 Libraries
27
9
2 Libraries
18
10
2 Libraries
2367
1
7 Libraries
1030
2
7 Libraries
70
3
5 Libraries
2288
4
4 Libraries
2817
5
4 Libraries
48
6
3 Libraries
18
7
3 Libraries
17
8
3 Libraries
27
9
2 Libraries
18
10
2 Libraries
2367
QUESTION
Unqualified lookup of operators in standard library templates
Asked 2022-Mar-05 at 16:301namespace N {
2 struct A {};
3
4 template<typename T>
5 constexpr bool operator<(const T&, const T&) { return true; }
6}
7
8constexpr bool operator<(const N::A&, const N::A&) { return false; }
9
10#include<functional>
11
12int main() {
13 static_assert(std::less<N::A>{}({}, {}), "assertion failed");
14}
15
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?
ANSWER
Answered 2022-Mar-05 at 16:30What 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.
Community Discussions contain sources that include Stack Exchange Network
QUESTION
Unqualified lookup of operators in standard library templates
Asked 2022-Mar-05 at 16:301namespace N {
2 struct A {};
3
4 template<typename T>
5 constexpr bool operator<(const T&, const T&) { return true; }
6}
7
8constexpr bool operator<(const N::A&, const N::A&) { return false; }
9
10#include<functional>
11
12int main() {
13 static_assert(std::less<N::A>{}({}, {}), "assertion failed");
14}
15
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?
ANSWER
Answered 2022-Mar-05 at 16:30What 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.
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources are not available at this moment for Assertion