Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<xhash>: Some member functions of transparent hash containers fail to work with initializer lists #5207

Open
frederick-vs-ja opened this issue Dec 27, 2024 · 0 comments · May be fixed by #5208

Comments

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Dec 27, 2024

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

Godbolt link

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.

STL/stl/inc/xhash

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant