ContainerHelpers.h#
Fully qualified name: carb/container/detail/ContainerHelpers.h
File members: carb/container/detail/ContainerHelpers.h
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.
#pragma once
#include "../../cpp/TypeTraits.h"
#include "TemplateHelpers.h"
#include <type_traits>
namespace carb::container
{
namespace detail
{
template <typename Key, typename Hasher, typename KeyEqual, typename = void>
struct SupportsTransparent : std::false_type
{
};
template <typename Key, typename Hasher, typename KeyEqual>
struct SupportsTransparent<Key, Hasher, KeyEqual, std::void_t<typename Hasher::is_transparent, typename KeyEqual::is_transparent>>
: std::true_type
{
};
struct is_iterator_impl
{
template <typename T>
using iter_traits_category = typename std::iterator_traits<T>::iterator_category;
template <typename T>
using input_iter_category =
std::enable_if_t<std::is_base_of<std::input_iterator_tag, iter_traits_category<T>>::value>;
};
template <typename T>
using is_input_iterator = supports_t<T, is_iterator_impl::iter_traits_category, is_iterator_impl::input_iter_category>;
template <typename T>
constexpr bool is_input_iterator_v = is_input_iterator<T>::value;
template <typename Alloc, bool = std::is_empty_v<Alloc> && !std::is_final_v<Alloc>>
class AllocBase : private Alloc
{
public:
using allocator_type = Alloc;
AllocBase() = default;
AllocBase(allocator_type a) : Alloc(std::move(a))
{
}
allocator_type& a() noexcept
{
return *this;
}
const allocator_type& a() const noexcept
{
return *this;
}
};
template <typename Alloc>
class AllocBase<Alloc, false>
{
Alloc m_alloc;
public:
using allocator_type = Alloc;
AllocBase() = default;
AllocBase(Alloc a) : m_alloc(std::move(a))
{
}
allocator_type& a() noexcept
{
return m_alloc;
}
const allocator_type& a() const noexcept
{
return m_alloc;
}
};
template <typename Hash, bool = std::is_empty_v<Hash> && !std::is_final_v<Hash>>
class HashBase : private Hash
{
public:
using hasher = Hash;
HashBase() = default;
HashBase(hasher h) : Hash(std::move(h))
{
}
const hasher& h() const noexcept
{
return *this;
}
};
template <typename Hash>
class HashBase<Hash, false>
{
Hash m_hash;
public:
using hasher = Hash;
HashBase() = default;
HashBase(hasher h) : m_hash(std::move(h))
{
}
const hasher& h() const noexcept
{
return m_hash;
}
};
template <typename KeyEqual, bool = std::is_empty_v<KeyEqual> && !std::is_final_v<KeyEqual>>
class KeyEqualBase : private KeyEqual
{
public:
using key_equal = KeyEqual;
KeyEqualBase() = default;
KeyEqualBase(key_equal k) : KeyEqual(std::move(k))
{
}
const key_equal& ke() const noexcept
{
return *this;
}
};
template <typename KeyEqual>
class KeyEqualBase<KeyEqual, false>
{
KeyEqual m_key_equal;
public:
using key_equal = KeyEqual;
KeyEqualBase() = default;
KeyEqualBase(key_equal k) : m_key_equal(std::move(k))
{
}
const key_equal& ke() const noexcept
{
return m_key_equal;
}
};
template <typename Key, typename Hash, typename KeyEqual>
class HashCompare : private HashBase<Hash>, private KeyEqualBase<KeyEqual>
{
using is_transparent_hash = SupportsTransparent<Key, Hash, KeyEqual>;
public:
using hasher = typename HashBase<Hash>::hasher;
using key_equal = typename KeyEqualBase<KeyEqual>::key_equal;
HashCompare() = default;
HashCompare(hasher hash, key_equal equal)
: HashBase<Hash>(std::move(hash)), KeyEqualBase<KeyEqual>(std::move(equal))
{
}
std::size_t operator()(const Key& key) const
{
return std::size_t(this->h()(key));
}
bool operator()(const Key& key1, const Key& key2) const
{
return this->ke()(key1, key2);
}
template <typename K, typename = std::enable_if_t<is_transparent_hash::value, K>>
std::size_t operator()(const K& key) const
{
return std::size_t(this->h()(key));
}
template <typename K1, typename K2, typename = std::enable_if_t<is_transparent_hash::value, K1>>
bool operator()(const K1& key1, const K2& key2) const
{
return this->ke()(key1, key2);
}
hasher hash_function() const
{
return this->h();
}
key_equal key_eq() const
{
return this->ke();
}
};
} // namespace detail
} // namespace carb::container