martinus/unordered_dense

[BUG] try_emplace() method report overloaded ambiguous with gcc 8.3

Opened this issue · 0 comments

lrita commented

Describe the bug

using try_emplace(Key &&) rvalue method is compiled failed with transparent/heterogeneous-accessible map.

To Reproduce

  1. add code in test/unit/transparent.cpp
TEST_CASE_MAP("transparent_rvalue", std::string, size_t, string_hash, string_eq) {
    auto map = map_t();
    std::string key = "abc";
    size_t value = 0;
    map.try_emplace(std::move(key), std::move(value));
}
  1. usng gcc 8.3
source scl_source enable devtoolset-8
export PATH=/opt/rh/devtoolset-8/root/usr/bin:$PATH
  1. compile failed.
[46/69] Compiling C++ object test/udm-test.p/unit_transparent.cpp.o
FAILED: test/udm-test.p/unit_transparent.cpp.o
c++ -Itest/udm-test.p -Itest -I../test -I../include -I../subprojects/doctest-2.4.9/doctest -I/data1/conda/envs/neal/include -fdiagnostics-color=always -DNDEBUG -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Werror -std=c++17 -O0 -g -DANKERL_UNORDERED_DENSE_HAS_BOOST=1 -DFMT_SHARED -pthread -Wno-stringop-overflow -Wshadow=global -Wno-array-bounds -Wconversion -Wextra -Wunreachable-code -Wuninitialized -pedantic-errors -Wno-unused-function -MD -MQ test/udm-test.p/unit_transparent.cpp.o -MF test/udm-test.p/unit_transparent.cpp.o.d -o test/udm-test.p/unit_transparent.cpp.o -c ../test/unit/transparent.cpp
../test/unit/transparent.cpp: In instantiation of ‘void DOCTEST_ANON_TMP_11() [with map_t = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, false>]’:
../test/unit/transparent.cpp:274:1:   required from ‘{anonymous}::DOCTEST_ANON_TMP_11ITERATOR<std::tuple<_El0, _El ...> >::DOCTEST_ANON_TMP_11ITERATOR(const char*, unsigned int, int) [with Type = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, false>; Rest = {ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>, deque_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::deque<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> > >, ankerl::unordered_dense::v4_4_0::bucket_type::standard>}]’
../test/unit/transparent.cpp:274:1:   required from here
../test/unit/transparent.cpp:281:5: error: call of overloaded ‘try_emplace(std::remove_reference<std::basic_string<char>&>::type, std::remove_reference<long unsigned int&>::type)’ is ambiguous
     map.try_emplace(std::move(vvv), std::move(ooo));
     ^~~
In file included from ../test/unit/transparent.cpp:1:
../include/ankerl/unordered_dense.h:1573:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(const Key&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char>, long unsigned int>*, std::vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > > >]’
     auto try_emplace(Key const& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1578:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(Key&&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char>, long unsigned int>*, std::vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > > >]’
     auto try_emplace(Key&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1600:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(K&&, Args&& ...) [with K = std::basic_string<char>; Args = {long unsigned int}; Q = long unsigned int; H = string_hash; KE = string_eq; typename std::enable_if<((is_map_v<Q> && is_transparent_v<H, KE>) && is_neither_convertible_v<K&&, typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>), bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = __gnu_cxx::__normal_iterator<std::pair<std::basic_string<char>, long unsigned int>*, std::vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > > >]’
     auto try_emplace(K&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../test/unit/transparent.cpp: In instantiation of ‘void DOCTEST_ANON_TMP_11() [with map_t = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>]’:
../test/unit/transparent.cpp:274:1:   required from ‘{anonymous}::DOCTEST_ANON_TMP_11ITERATOR<std::tuple<_El0, _El ...> >::DOCTEST_ANON_TMP_11ITERATOR(const char*, unsigned int, int) [with Type = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>; Rest = {deque_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::deque<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> > >, ankerl::unordered_dense::v4_4_0::bucket_type::standard>}]’
../test/unit/transparent.cpp:274:1:   required from ‘{anonymous}::DOCTEST_ANON_TMP_11ITERATOR<std::tuple<_El0, _El ...> >::DOCTEST_ANON_TMP_11ITERATOR(const char*, unsigned int, int) [with Type = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, false>; Rest = {ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>, deque_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::deque<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> > >, ankerl::unordered_dense::v4_4_0::bucket_type::standard>}]’
../test/unit/transparent.cpp:274:1:   required from here
../test/unit/transparent.cpp:281:5: error: call of overloaded ‘try_emplace(std::remove_reference<std::basic_string<char>&>::type, std::remove_reference<long unsigned int&>::type)’ is ambiguous
     map.try_emplace(std::move(vvv), std::move(ooo));
     ^~~
In file included from ../test/unit/transparent.cpp:1:
../include/ankerl/unordered_dense.h:1573:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(const Key&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = true; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = ankerl::unordered_dense::v4_4_0::segmented_vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, 4096>::iter_t<false>]’
     auto try_emplace(Key const& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1578:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(Key&&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = true; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = ankerl::unordered_dense::v4_4_0::segmented_vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, 4096>::iter_t<false>]’
     auto try_emplace(Key&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1600:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(K&&, Args&& ...) [with K = std::basic_string<char>; Args = {long unsigned int}; Q = long unsigned int; H = string_hash; KE = string_eq; typename std::enable_if<((is_map_v<Q> && is_transparent_v<H, KE>) && is_neither_convertible_v<K&&, typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>), bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::allocator<std::pair<std::basic_string<char>, long unsigned int> >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = true; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = ankerl::unordered_dense::v4_4_0::segmented_vector<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, 4096>::iter_t<false>]’
     auto try_emplace(K&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../test/unit/transparent.cpp: In instantiation of ‘void DOCTEST_ANON_TMP_11() [with map_t = deque_map<std::basic_string<char>, long unsigned int, string_hash, string_eq>]’:
../test/unit/transparent.cpp:274:1:   recursively required from ‘{anonymous}::DOCTEST_ANON_TMP_11ITERATOR<std::tuple<_El0, _El ...> >::DOCTEST_ANON_TMP_11ITERATOR(const char*, unsigned int, int) [with Type = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>; Rest = {deque_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::deque<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> > >, ankerl::unordered_dense::v4_4_0::bucket_type::standard>}]’
../test/unit/transparent.cpp:274:1:   required from ‘{anonymous}::DOCTEST_ANON_TMP_11ITERATOR<std::tuple<_El0, _El ...> >::DOCTEST_ANON_TMP_11ITERATOR(const char*, unsigned int, int) [with Type = ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char>, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char>, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, false>; Rest = {ankerl::unordered_dense::v4_4_0::detail::table<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> >, ankerl::unordered_dense::v4_4_0::bucket_type::standard, true>, deque_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int, string_hash, string_eq, std::deque<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, long unsigned int> > >, ankerl::unordered_dense::v4_4_0::bucket_type::standard>}]’
../test/unit/transparent.cpp:274:1:   required from here
../test/unit/transparent.cpp:281:5: error: call of overloaded ‘try_emplace(std::remove_reference<std::basic_string<char>&>::type, std::remove_reference<long unsigned int&>::type)’ is ambiguous
     map.try_emplace(std::move(vvv), std::move(ooo));
     ^~~
In file included from ../test/unit/transparent.cpp:1:
../include/ankerl/unordered_dense.h:1573:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(const Key&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::deque<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = std::_Deque_iterator<std::pair<std::basic_string<char>, long unsigned int>, std::pair<std::basic_string<char>, long unsigned int>&, std::pair<std::basic_string<char>, long unsigned int>*>]’
     auto try_emplace(Key const& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1578:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(Key&&, Args&& ...) [with Args = {long unsigned int}; Q = long unsigned int; typename std::enable_if<is_map_v<Q>, bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::deque<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = std::_Deque_iterator<std::pair<std::basic_string<char>, long unsigned int>, std::pair<std::basic_string<char>, long unsigned int>&, std::pair<std::basic_string<char>, long unsigned int>*>]’
     auto try_emplace(Key&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
../include/ankerl/unordered_dense.h:1600:10: note: candidate: ‘std::pair<typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, bool> ankerl::unordered_dense::v4_4_0::detail::table<Key, T, Hash, KeyEqual, AllocatorOrContainer, Bucket, IsSegmented>::try_emplace(K&&, Args&& ...) [with K = std::basic_string<char>; Args = {long unsigned int}; Q = long unsigned int; H = string_hash; KE = string_eq; typename std::enable_if<((is_map_v<Q> && is_transparent_v<H, KE>) && is_neither_convertible_v<K&&, typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer, 4096>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>), bool>::type <anonymous> = 1; Key = std::basic_string<char>; T = long unsigned int; Hash = string_hash; KeyEqual = string_eq; AllocatorOrContainer = std::deque<std::pair<std::basic_string<char>, long unsigned int>, std::allocator<std::pair<std::basic_string<char>, long unsigned int> > >; Bucket = ankerl::unordered_dense::v4_4_0::bucket_type::standard; bool IsSegmented = false; typename std::conditional<is_map_v<T>, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::iterator, typename std::conditional<is_detected_v<ankerl::unordered_dense::v4_4_0::detail::detect_iterator, AllocatorOrContainer>, AllocatorOrContainer, typename std::conditional<IsSegmented, ankerl::unordered_dense::v4_4_0::segmented_vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer>, std::vector<typename std::conditional<is_map_v<T>, std::pair<_T1, _T2>, Key>::type, AllocatorOrContainer> >::type>::type::const_iterator>::type = std::_Deque_iterator<std::pair<std::basic_string<char>, long unsigned int>, std::pair<std::basic_string<char>, long unsigned int>&, std::pair<std::basic_string<char>, long unsigned int>*>]’
     auto try_emplace(K&& key, Args&&... args) -> std::pair<iterator, bool> {
          ^~~~~~~~~~~
  1. gcc 11.2.0 compile ok.

Expected behavior
A clear and concise description of what you expected to happen.

System (please complete the following information):

  • OS: Linux
  • Compiler: g++
  • Version 8.3.1

Additional context

I modify the method with this patch will suppress this fault. Is there a better way to fix it ? Maybe using absl’s key_arg<K> way ?

diff --git a/include/ankerl/unordered_dense.h b/include/ankerl/unordered_dense.h
index 2aaacd6..d841bad 100644
--- a/include/ankerl/unordered_dense.h
+++ b/include/ankerl/unordered_dense.h
@@ -480,6 +480,14 @@ constexpr bool is_transparent_v = is_detected_v<detect_is_transparent, Hash> &&
 template <typename From, typename To1, typename To2>
 constexpr bool is_neither_convertible_v = !std::is_convertible_v<From, To1> && !std::is_convertible_v<From, To2>;

+template<class T>
+struct remove_cvref
+{
+    using type = std::remove_cv_t<std::remove_reference_t<T>>;
+};
+template< typename T >
+using remove_cvref_t = typename remove_cvref<T>::type;
+
 template <typename T>
 constexpr bool has_reserve = is_detected_v<detect_reserve, T>;

@@ -1595,7 +1603,7 @@ public:
         typename Q = T,
         typename H = Hash,
         typename KE = KeyEqual,
-        std::enable_if_t<is_map_v<Q> && is_transparent_v<H, KE> && is_neither_convertible_v<K&&, iterator, const_iterator>,
+        std::enable_if_t<is_map_v<Q> && is_transparent_v<H, KE> && is_neither_convertible_v<K&&, iterator, const_iterator> && !std::is_same_v<remove_cvref_t<K>, Key>,
                          bool> = true>
     auto try_emplace(K&& key, Args&&... args) -> std::pair<iterator, bool> {
         return do_try_emplace(std::forward<K>(key), std::forward<Args>(args)...);
@@ -1607,7 +1615,7 @@ public:
         typename Q = T,
         typename H = Hash,
         typename KE = KeyEqual,
-        std::enable_if_t<is_map_v<Q> && is_transparent_v<H, KE> && is_neither_convertible_v<K&&, iterator, const_iterator>,
+        std::enable_if_t<is_map_v<Q> && is_transparent_v<H, KE> && is_neither_convertible_v<K&&, iterator, const_iterator> && !std::is_same_v<remove_cvref_t<K>, Key>,
                          bool> = true>
     auto try_emplace(const_iterator /*hint*/, K&& key, Args&&... args) -> iterator {
         return do_try_emplace(std::forward<K>(key), std::forward<Args>(args)...).first;