Found while running libc++'s tests with MSVC's STL. * `libcxx/test/std/algorithms/alg.modifying.operations/alg.unique/ranges_unique_copy.pass.cpp` + Fix MSVC "warning C4389: '`==`': signed/unsigned mismatch". + This was x86-specific for me. The LHS is `int` and the RHS is `size_t`. We know the `array`'s size, so `static_cast<int>` is certainly safe, and this matches the following `numberOfProj` comparisons. * `libcxx/test/std/containers/sequences/insert_range_sequence_containers.h` + Fix MSVC "warning C4267: 'argument': conversion from '`size_t`' to '`const int`', possible loss of data". + `test_case.index` is `size_t`:b85f1f9b18/libcxx/test/std/containers/insert_range_helpers.h (L65-L68)+ But the container's `difference_type` is `int`:b85f1f9b18/libcxx/test/support/test_allocator.h (L65-L76)+ I introduced an alias `D` to make the long line more readable. * `libcxx/test/std/containers/unord/unord.map/eq.different_hash.pass.cpp` * `libcxx/test/std/containers/unord/unord.multimap/eq.different_hash.pass.cpp` * `libcxx/test/std/containers/unord/unord.multiset/eq.different_hash.pass.cpp` * `libcxx/test/std/containers/unord/unord.set/eq.different_hash.pass.cpp` + Fix MSVC "warning C6297: Arithmetic overflow. Results might not be an expected value." + This warning is almost annoying enough to outright disable, but we use similar `static_cast`s to deal with sign/truncation warnings elsewhere, because there's some value in ensuring that product code is clean with respect to these warnings. If there were many more occurrences, then disabling the warning would be appropriate. + Cleanup: Change 2 inconsistently unqualified occurrences of `size_t` to `std::size_t`. * `libcxx/test/std/containers/views/mdspan/layout_stride/index_operator.pass.cpp` + Fix MSVC "warning C4244: 'initializing': conversion from '`__int64`' to '`size_t`', possible loss of data". + This was x86-specific for me. The `args` are indeed `int64_t`, and we're storing the result in `size_t`, so we should cast. * `libcxx/test/std/ranges/range.utility/range.utility.conv/container.h` + Fix MSVC "warning C4244: 'initializing': conversion from '`ptrdiff_t`' to '`int`', possible loss of data". + Fix MSVC "warning C4267: 'initializing': conversion from '`size_t`' to '`int`', possible loss of data". + We're initializing `int size_`, so we should explicitly cast from pointer subtraction and `std::ranges::size`. * `libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_for_overwrite.pass.cpp` * `libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared_for_overwrite.pass.cpp` * `libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.create/make_unique_for_overwrite.default_init.pass.cpp` + Fix MSVC "warning C4309: 'initializing': truncation of constant value". + MSVC emits this warning because `0xDE` is outside the range of `char` (signed by default in our implementation). * `libcxx/test/support/concat_macros.h` + Fix MSVC "warning C4244: 'argument': conversion from '`char16_t`' to '`const char`', possible loss of data". + Fix MSVC "warning C4244: 'argument': conversion from '`unsigned int`' to '`const char`', possible loss of data". + This code was very recently introduced by @mordante in #73395.
145 lines
4.4 KiB
C++
145 lines
4.4 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H
|
|
#define RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H
|
|
|
|
#include <algorithm>
|
|
#include <concepts>
|
|
#include <cstddef>
|
|
|
|
enum class CtrChoice { Invalid, DefaultCtrAndInsert, BeginEndPair, FromRangeT, DirectCtr };
|
|
|
|
enum class InserterChoice { Invalid, Insert, PushBack };
|
|
|
|
// Allows checking that `ranges::to` correctly follows the order of priority of different constructors -- e.g., if
|
|
// 3 constructors are available, the `from_range_t` constructor is chosen in favor of the constructor taking two
|
|
// iterators, etc.
|
|
template <class ElementType, CtrChoice Rank, InserterChoice Inserter = InserterChoice::Insert, bool CanReserve = false>
|
|
struct Container {
|
|
CtrChoice ctr_choice = CtrChoice::Invalid;
|
|
InserterChoice inserter_choice = InserterChoice::Invalid;
|
|
bool called_reserve = false;
|
|
|
|
int extra_arg1 = 0;
|
|
char extra_arg2 = 0;
|
|
|
|
using value_type = ElementType;
|
|
static constexpr int Capacity = 8;
|
|
int size_ = 0;
|
|
ElementType buffer_[Capacity] = {};
|
|
|
|
// Case 1 -- construct directly from the range.
|
|
|
|
constexpr explicit Container(std::ranges::input_range auto&& in)
|
|
requires(Rank >= CtrChoice::DirectCtr)
|
|
: ctr_choice(CtrChoice::DirectCtr), size_(static_cast<int>(std::ranges::size(in))) {
|
|
std::ranges::copy(in, begin());
|
|
}
|
|
|
|
// Check that `ranges::to` can also pass extra parameters.
|
|
constexpr explicit Container(std::ranges::input_range auto&& in, int arg1, char arg2)
|
|
requires(Rank >= CtrChoice::DirectCtr)
|
|
: Container(in) {
|
|
extra_arg1 = arg1;
|
|
extra_arg2 = arg2;
|
|
}
|
|
|
|
// Case 2 -- use `from_range_t` constructor.
|
|
|
|
constexpr Container(std::from_range_t, std::ranges::input_range auto&& in)
|
|
requires(Rank >= CtrChoice::FromRangeT)
|
|
: ctr_choice(CtrChoice::FromRangeT), size_(static_cast<int>(std::ranges::size(in))) {
|
|
std::ranges::copy(in, begin());
|
|
}
|
|
|
|
constexpr Container(std::from_range_t, std::ranges::input_range auto&& in, int arg1, char arg2)
|
|
requires(Rank >= CtrChoice::FromRangeT)
|
|
: Container(std::from_range, in) {
|
|
extra_arg1 = arg1;
|
|
extra_arg2 = arg2;
|
|
}
|
|
|
|
// Case 3 -- use begin-end pair.
|
|
|
|
template <class Iter>
|
|
constexpr Container(Iter b, Iter e)
|
|
requires(Rank >= CtrChoice::BeginEndPair)
|
|
: ctr_choice(CtrChoice::BeginEndPair), size_(static_cast<int>(e - b)) {
|
|
std::ranges::copy(b, e, begin());
|
|
}
|
|
|
|
template <class Iter>
|
|
constexpr Container(Iter b, Iter e, int arg1, char arg2)
|
|
requires(Rank >= CtrChoice::BeginEndPair)
|
|
: Container(b, e) {
|
|
extra_arg1 = arg1;
|
|
extra_arg2 = arg2;
|
|
}
|
|
|
|
// Case 4 -- default-construct and insert, reserving the size if possible.
|
|
|
|
constexpr Container()
|
|
requires(Rank >= CtrChoice::DefaultCtrAndInsert)
|
|
: ctr_choice(CtrChoice::DefaultCtrAndInsert) {}
|
|
|
|
constexpr Container(int arg1, char arg2)
|
|
requires(Rank >= CtrChoice::DefaultCtrAndInsert)
|
|
: ctr_choice(CtrChoice::DefaultCtrAndInsert), extra_arg1(arg1), extra_arg2(arg2) {}
|
|
|
|
constexpr ElementType* begin() { return buffer_; }
|
|
constexpr ElementType* end() { return buffer_ + size_; }
|
|
constexpr std::size_t size() const { return size_; }
|
|
|
|
template <class T>
|
|
constexpr void push_back(T val)
|
|
requires(Inserter >= InserterChoice::PushBack)
|
|
{
|
|
inserter_choice = InserterChoice::PushBack;
|
|
buffer_[size_] = val;
|
|
++size_;
|
|
}
|
|
|
|
template <class T>
|
|
constexpr ElementType* insert(ElementType* where, T val)
|
|
requires(Inserter >= InserterChoice::Insert)
|
|
{
|
|
assert(size() + 1 <= Capacity);
|
|
|
|
inserter_choice = InserterChoice::Insert;
|
|
|
|
std::shift_right(where, end(), 1);
|
|
*where = val;
|
|
++size_;
|
|
|
|
return where;
|
|
}
|
|
|
|
constexpr void reserve(size_t)
|
|
requires CanReserve
|
|
{
|
|
called_reserve = true;
|
|
}
|
|
|
|
constexpr std::size_t capacity() const
|
|
requires CanReserve
|
|
{
|
|
return Capacity;
|
|
}
|
|
|
|
constexpr std::size_t max_size() const
|
|
requires CanReserve
|
|
{
|
|
return Capacity;
|
|
}
|
|
|
|
friend constexpr bool operator==(const Container&, const Container&) = default;
|
|
};
|
|
|
|
#endif // RANGES_RANGE_UTILITY_RANGE_UTILITY_CONV_CONTAINER_H
|