-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Closed
Labels
bugSomething isn't workingSomething isn't workingfixedSomething works now, yay!Something works now, yay!
Description
Describe the bug
From DevCom-10819520.
The following program don't compile with MSVC STL.
#include <unordered_map>
#include <unordered_set>
struct elem {
elem(unsigned val) : value(val) {}
unsigned value = 0;
};
struct hash {
using is_transparent = void;
unsigned operator()(elem e) const { return e.value; }
};
struct equal {
using is_transparent = void;
unsigned operator()(elem e1, elem e2) const { return e1.value == e2.value; }
};
int main() {
std::unordered_map<elem, int, hash, equal> map;
(void)map.find(1u); // OK
(void)map.find({1u}); // MSVC: compile error, GCC: OK
std::unordered_set<elem, hash, equal> set;
(void)set.find(1u); // OK
(void)set.find({1u}); // MSVC: compile error, GCC: OK
}Command-line test case
Expected behavior
The program compiles. No "reference to cv void" is attempted to formed.
I think this bug is due to wrong _Deduce_key type.
Lines 108 to 121 in 9082000
| #if _HAS_CXX20 | |
| template <class _Kty, class _Hasher, class _Keyeq> | |
| requires _Is_transparent_v<_Hasher> && _Is_transparent_v<_Keyeq> | |
| struct _Uhash_choose_transparency<_Kty, _Hasher, _Keyeq> { | |
| // transparency selector for transparent hashed containers | |
| template <class _Keyty> | |
| using _Deduce_key = const _Keyty&; | |
| template <class _Container, class _Kx> | |
| static constexpr bool _Supports_transparency = | |
| !disjunction_v<is_convertible<_Kx, typename _Container::const_iterator>, | |
| is_convertible<_Kx, typename _Container::iterator>>; | |
| }; | |
| #endif // _HAS_CXX20 |
When brace initializer list is used as argument, the implementation should (as-if) fallback to the non-transparent overloads. But the wrong const void& type is attempted to be formed now.
STL version
All existing versions since VS 2019 16.5 (which got WG21-P1690R1 implemented).
Additional context
BTW, MSVC STL currently accepts the following bogus program even before C++20 (Godbolt link).
#include <unordered_set>
int main()
{
std::unordered_set<int> m{1, 2, 3};
auto it = m.find<void()>(1);
return it == m.end();
}Although this may still be conforming due to [member.functions]/2.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingfixedSomething works now, yay!Something works now, yay!