Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/libartbase/base/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 25 kB image not shown  

Quelle  intrusive_forward_list_test.cc

  Sprache: C
 

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <algorithm>
#include <forward_list>
#include <type_traits>
#include <vector>

#include "gtest/gtest.h"
#include "intrusive_forward_list.h"

namespace art {

struct IFLTestValue : public IntrusiveForwardListNode<IFLTestValue> {
  // Deliberately not explicit.
  IFLTestValue(int v) : value(v) { }  // NOLINT(runtime/explicit)

  int value;
};
using IFLTestValueList = IntrusiveForwardList<IFLTestValue>;
using ConstIFLTestValueList = IntrusiveForwardList<const IFLTestValue>;

bool operator==(const IFLTestValue& lhs, const IFLTestValue& rhs) {
  return lhs.value == rhs.value;
}

bool operator<(const IFLTestValue& lhs, const IFLTestValue& rhs) {
  return lhs.value < rhs.value;
}

struct IFLTestValue2 {
  // Deliberately not explicit.
  IFLTestValue2(int v) : hook(), value(v) { }  // NOLINT(runtime/explicit)

  IntrusiveForwardListHook hook;
  int value;
};
using IFLTestValue2List =
    IntrusiveForwardList<IFLTestValue2, IntrusiveForwardListMemberHookTraits<IFLTestValue2>>;

bool operator==(const IFLTestValue2& lhs, const IFLTestValue2& rhs) {
  return lhs.value == rhs.value;
}

bool operator<(const IFLTestValue2& lhs, const IFLTestValue2& rhs) {
  return lhs.value < rhs.value;
}

#define ASSERT_LISTS_EQUAL(expected, value)                                         \
  do {                                                                              \
    ASSERT_EQ((expected).empty(), (value).empty());                                 \
    ASSERT_EQ(std::distance((expected).begin(), (expected).end()),                  \
              std::distance((value).begin(), (value).end()));                       \
    ASSERT_TRUE(std::equal((expected).begin(), (expected).end(), (value).begin())); \
  } while (false)

class IntrusiveForwardListTest : public ::testing::Test {
 public:
  template <typename ListType>
  void IteratorToConstIterator();

  template <typename ListType>
  void IteratorOperators();

  template <typename ListType>
  void ConstructRange();

  template <typename ListType>
  void Assign();

  template <typename ListType>
  void PushPop();

  template <typename ListType>
  void InsertAfter1();

  template <typename ListType>
  void InsertAfter2();

  template <typename ListType>
  void EraseAfter1();

  template <typename ListType>
  void EraseAfter2();

  template <typename ListType>
  void SwapClear();

  template <typename ListType>
  void SpliceAfter();

  template <typename ListType>
  void Remove();

  template <typename ListType>
  void Unique();

  template <typename ListType>
  void Merge();

  template <typename ListType>
  void Sort1();

  template <typename ListType>
  void Sort2();

  template <typename ListType>
  void Reverse();

  template <typename ListType>
  void ModifyValue();
};

template <typename ListType>
void IntrusiveForwardListTest::IteratorToConstIterator() {
  ListType ifl;
  typename ListType::iterator begin = ifl.begin();
  typename ListType::const_iterator cbegin = ifl.cbegin();
  typename ListType::const_iterator converted_begin = begin;
  ASSERT_TRUE(converted_begin == cbegin);
}

TEST_F(IntrusiveForwardListTest, IteratorToConstIterator) {
  IteratorToConstIterator<IFLTestValueList>();
  IteratorToConstIterator<ConstIFLTestValueList>();
  IteratorToConstIterator<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::IteratorOperators() {
  using ValueType = typename ListType::value_type;
  ListType ifl;
  ASSERT_TRUE(ifl.begin() == ifl.cbegin());
  ASSERT_FALSE(ifl.begin() != ifl.cbegin());
  ASSERT_TRUE(ifl.end() == ifl.cend());
  ASSERT_FALSE(ifl.end() != ifl.cend());

  ASSERT_TRUE(ifl.begin() == ifl.end());  // Empty.
  ASSERT_FALSE(ifl.begin() != ifl.end());  // Empty.

  ValueType value(1);
  ifl.insert_after(ifl.cbefore_begin(), value);

  ASSERT_FALSE(ifl.begin() == ifl.end());  // Not empty.
  ASSERT_TRUE(ifl.begin() != ifl.end());  // Not empty.
}

TEST_F(IntrusiveForwardListTest, IteratorOperators) {
  IteratorOperators<IFLTestValueList>();
  IteratorOperators<ConstIFLTestValueList>();
  IteratorOperators<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::ConstructRange() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 127 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
}

TEST_F(IntrusiveForwardListTest, ConstructRange) {
  ConstructRange<IFLTestValueList>();
  ConstructRange<ConstIFLTestValueList>();
  ConstructRange<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Assign() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref1({ 285 });
  std::vector<std::remove_const_t<ValueType>> storage1(ref1.begin(), ref1.end());
  ListType ifl;
  ifl.assign(storage1.begin(), storage1.end());
  ASSERT_LISTS_EQUAL(ref1, ifl);
  std::forward_list<int> ref2({ 713 });
  std::vector<std::remove_const_t<ValueType>> storage2(ref2.begin(), ref2.end());
  ifl.assign(storage2.begin(), storage2.end());
  ASSERT_LISTS_EQUAL(ref2, ifl);
}

TEST_F(IntrusiveForwardListTest, Assign) {
  Assign<IFLTestValueList>();
  Assign<ConstIFLTestValueList>();
  Assign<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::PushPop() {
  using ValueType = typename ListType::value_type;
  ValueType value3(3);
  ValueType value7(7);
  std::forward_list<int> ref;
  ListType ifl;
  ASSERT_LISTS_EQUAL(ref, ifl);
  ref.push_front(3);
  ifl.push_front(value3);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(3, ifl.front());
  ref.push_front(7);
  ifl.push_front(value7);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(7, ifl.front());
  ref.pop_front();
  ifl.pop_front();
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(3, ifl.front());
  ref.pop_front();
  ifl.pop_front();
  ASSERT_LISTS_EQUAL(ref, ifl);
}

TEST_F(IntrusiveForwardListTest, PushPop) {
  PushPop<IFLTestValueList>();
  PushPop<ConstIFLTestValueList>();
  PushPop<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::InsertAfter1() {
  using ValueType = typename ListType::value_type;
  ValueType value4(4);
  ValueType value8(8);
  ValueType value5(5);
  ValueType value3(3);
  std::forward_list<int> ref;
  ListType ifl;

  auto ref_it = ref.insert_after(ref.before_begin(), 4);
  auto ifl_it = ifl.insert_after(ifl.before_begin(), value4);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);
  CHECK(ref_it == ref.begin());
  ASSERT_TRUE(ifl_it == ifl.begin());

  ref_it = ref.insert_after(ref.begin(), 8);
  ifl_it = ifl.insert_after(ifl.begin(), value8);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);
  CHECK(ref_it != ref.end());
  ASSERT_TRUE(ifl_it != ifl.end());
  CHECK(++ref_it == ref.end());
  ASSERT_TRUE(++ifl_it == ifl.end());

  ref_it = ref.insert_after(ref.begin(), 5);
  ifl_it = ifl.insert_after(ifl.begin(), value5);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);

  ref_it = ref.insert_after(ref_it, 3);
  ifl_it = ifl.insert_after(ifl_it, value3);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);
}

TEST_F(IntrusiveForwardListTest, InsertAfter1) {
  InsertAfter1<IFLTestValueList>();
  InsertAfter1<ConstIFLTestValueList>();
  InsertAfter1<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::InsertAfter2() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref;
  ListType ifl;

  auto ref_it = ref.insert_after(ref.before_begin(), { 285 });
  std::vector<std::remove_const_t<ValueType>> storage1({ { 2 }, { 8 }, { 5 } });
  auto ifl_it = ifl.insert_after(ifl.before_begin(), storage1.begin(), storage1.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);

  std::vector<std::remove_const_t<ValueType>> storage2({ { 7 }, { 2 } });
  ref_it = ref.insert_after(ref.begin(), { 72 });
  ifl_it = ifl.insert_after(ifl.begin(), storage2.begin(), storage2.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(*ref_it, *ifl_it);

  std::vector<std::remove_const_t<ValueType>> storage3({ { 1 }, { 3 }, { 4 }, { 9 } });
  ref_it = ref.begin();
  ifl_it = ifl.begin();
  std::advance(ref_it, std::distance(ref.begin(), ref.end()) - 1);
  std::advance(ifl_it, std::distance(ifl.begin(), ifl.end()) - 1);
  ref_it = ref.insert_after(ref_it, { 1349 });
  ifl_it = ifl.insert_after(ifl_it, storage3.begin(), storage3.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
}

TEST_F(IntrusiveForwardListTest, InsertAfter2) {
  InsertAfter2<IFLTestValueList>();
  InsertAfter2<ConstIFLTestValueList>();
  InsertAfter2<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::EraseAfter1() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 12745 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 5);

  auto ref_it = ref.begin();
  auto ifl_it = ifl.begin();
  std::advance(ref_it, 2);
  std::advance(ifl_it, 2);
  ref_it = ref.erase_after(ref_it);
  ifl_it = ifl.erase_after(ifl_it);
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 4);
  CHECK(ref_it != ref.end());
  ASSERT_TRUE(ifl_it != ifl.end());
  CHECK(++ref_it == ref.end());
  ASSERT_TRUE(++ifl_it == ifl.end());

  ref_it = ref.begin();
  ifl_it = ifl.begin();
  std::advance(ref_it, 2);
  std::advance(ifl_it, 2);
  ref_it = ref.erase_after(ref_it);
  ifl_it = ifl.erase_after(ifl_it);
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 3);
  CHECK(ref_it == ref.end());
  ASSERT_TRUE(ifl_it == ifl.end());

  ref_it = ref.erase_after(ref.begin());
  ifl_it = ifl.erase_after(ifl.begin());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 2);
  CHECK(ref_it != ref.end());
  ASSERT_TRUE(ifl_it != ifl.end());
  CHECK(++ref_it == ref.end());
  ASSERT_TRUE(++ifl_it == ifl.end());

  ref_it = ref.erase_after(ref.before_begin());
  ifl_it = ifl.erase_after(ifl.before_begin());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 1);
  CHECK(ref_it == ref.begin());
  ASSERT_TRUE(ifl_it == ifl.begin());

  ref_it = ref.erase_after(ref.before_begin());
  ifl_it = ifl.erase_after(ifl.before_begin());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 0);
  CHECK(ref_it == ref.begin());
  ASSERT_TRUE(ifl_it == ifl.begin());
}

TEST_F(IntrusiveForwardListTest, EraseAfter1) {
  EraseAfter1<IFLTestValueList>();
  EraseAfter1<ConstIFLTestValueList>();
  EraseAfter1<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::EraseAfter2() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 127453289 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 9);

  auto ref_it = ref.begin();
  auto ifl_it = ifl.begin();
  std::advance(ref_it, 3);
  std::advance(ifl_it, 3);
  ref_it = ref.erase_after(ref.begin(), ref_it);
  ifl_it = ifl.erase_after(ifl.begin(), ifl_it);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ASSERT_EQ(std::distance(ref.begin(), ref_it), std::distance(ifl.begin(), ifl_it));
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 7);

  ref_it = ref.erase_after(ref_it, ref.end());
  ifl_it = ifl.erase_after(ifl_it, ifl.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK(ref_it == ref.end());
  ASSERT_TRUE(ifl_it == ifl.end());
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 2);

  ref_it = ref.erase_after(ref.before_begin(), ref.end());
  ifl_it = ifl.erase_after(ifl.before_begin(), ifl.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK(ref_it == ref.end());
  ASSERT_TRUE(ifl_it == ifl.end());
  CHECK_EQ(std::distance(ref.begin(), ref.end()), 0);
}

TEST_F(IntrusiveForwardListTest, EraseAfter2) {
  EraseAfter2<IFLTestValueList>();
  EraseAfter2<ConstIFLTestValueList>();
  EraseAfter2<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::SwapClear() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref1({ 127 });
  std::vector<std::remove_const_t<ValueType>> storage1(ref1.begin(), ref1.end());
  ListType ifl1(storage1.begin(), storage1.end());
  std::forward_list<int> ref2({ 386 });
  std::vector<std::remove_const_t<ValueType>> storage2(ref2.begin(), ref2.end());
  ListType ifl2(storage2.begin(), storage2.end());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  ref1.swap(ref2);
  ifl1.swap(ifl2);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  ref1.clear();
  ifl1.clear();
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  swap(ref1, ref2);
  swap(ifl1, ifl2);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  ref1.clear();
  ifl1.clear();
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
}

TEST_F(IntrusiveForwardListTest, SwapClear) {
  SwapClear<IFLTestValueList>();
  SwapClear<ConstIFLTestValueList>();
  SwapClear<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::SpliceAfter() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref1({ 312745487 });
  std::forward_list<int> ref2;
  std::vector<std::remove_const_t<ValueType>> storage(ref1.begin(), ref1.end());
  ListType ifl1(storage.begin(), storage.end());
  ListType ifl2;
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move everything to ref2/ifl2.
  ref2.splice_after(ref2.before_begin(), ref1);
  ifl2.splice_after(ifl2.before_begin(), ifl1);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move first element (3) to ref1/ifl1.
  ref1.splice_after(ref1.before_begin(), ref2, ref2.before_begin());
  ifl1.splice_after(ifl1.before_begin(), ifl2, ifl2.before_begin());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move second element (2) to ref1/ifl1 after the first element (3).
  ref1.splice_after(ref1.begin(), ref2, ref2.begin());
  ifl1.splice_after(ifl1.begin(), ifl2, ifl2.begin());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move everything from ref2/ifl2 between the 2 elements now in ref1/ifl1.
  ref1.splice_after(ref1.begin(), ref2);
  ifl1.splice_after(ifl1.begin(), ifl2);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  std::forward_list<int> check({ 317454872 });
  ASSERT_LISTS_EQUAL(check, ifl1);
  ASSERT_TRUE(ifl2.empty());

  // Empty splice_after().
  ref2.splice_after(
      ref2.before_begin(), ref1, ref1.before_begin(), ref1.begin());
  ifl2.splice_after(ifl2.before_begin(), ifl1, ifl1.before_begin(), ifl1.begin());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move { 1, 7 } to ref2/ifl2.
  auto ref_it = ref1.begin();
  auto ifl_it = ifl1.begin();
  std::advance(ref_it, 3);
  std::advance(ifl_it, 3);
  ref2.splice_after(ref2.before_begin(), ref1, ref1.begin(), ref_it);
  ifl2.splice_after(ifl2.before_begin(), ifl1, ifl1.begin(), ifl_it);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  // Move { 8, 7, 2 } to the beginning of ref1/ifl1.
  ref_it = ref1.begin();
  ifl_it = ifl1.begin();
  std::advance(ref_it, 3);
  std::advance(ifl_it, 3);
  ref1.splice_after(ref1.before_begin(), ref1, ref_it, ref1.end());
  ifl1.splice_after(ifl1.before_begin(), ifl1, ifl_it, ifl1.end());
  ASSERT_LISTS_EQUAL(ref1, ifl1);

  check.assign({ 8723454 });
  ASSERT_LISTS_EQUAL(check, ifl1);
  check.assign({ 17 });
  ASSERT_LISTS_EQUAL(check, ifl2);

  // Move all but the first element to ref2/ifl2.
  ref_it = ref2.begin();
  ifl_it = ifl2.begin();
  std::advance(ref_it, 1);
  std::advance(ifl_it, 1);
  ref2.splice_after(ref_it, ref1, ref1.begin(), ref1.end());
  ifl2.splice_after(ifl_it, ifl1, ifl1.begin(), ifl1.end());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);

  check.assign({8});
  ASSERT_LISTS_EQUAL(check, ifl1);

  // Move the first element of ref1/ifl1 to the beginning of ref1/ifl1 (do nothing).
  ref1.splice_after(ref1.before_begin(), ref1, ref1.before_begin());
  ifl1.splice_after(ifl1.before_begin(), ifl1, ifl1.before_begin());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(check, ifl1);

  // Move the first element of ref2/ifl2 after itself (do nothing).
  ref1.splice_after(ref1.begin(), ref1, ref1.before_begin());
  ifl1.splice_after(ifl1.begin(), ifl1, ifl1.before_begin());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(check, ifl1);

  check.assign({ 17723454 });
  ASSERT_LISTS_EQUAL(check, ifl2);

  // Move the first element of ref2/ifl2 to the beginning of ref2/ifl2 (do nothing).
  ref2.splice_after(ref2.before_begin(), ref2, ref2.before_begin());
  ifl2.splice_after(ifl2.before_begin(), ifl2, ifl2.before_begin());
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  ASSERT_LISTS_EQUAL(check, ifl2);

  // Move the first element of ref2/ifl2 after itself (do nothing).
  ref2.splice_after(ref2.begin(), ref2, ref2.before_begin());
  ifl2.splice_after(ifl2.begin(), ifl2, ifl2.before_begin());
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  ASSERT_LISTS_EQUAL(check, ifl2);
}

TEST_F(IntrusiveForwardListTest, SpliceAfter) {
  SpliceAfter<IFLTestValueList>();
  SpliceAfter<ConstIFLTestValueList>();
  SpliceAfter<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Remove() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 312745487 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  ref.remove(1);
  ifl.remove(1);
  ASSERT_LISTS_EQUAL(ref, ifl);
  ref.remove(4);
  ifl.remove(4);
  ASSERT_LISTS_EQUAL(ref, ifl);
  auto odd = [](ValueType value) { return (value.value & 1) != 0; };
  ref.remove_if(odd);
  ifl.remove_if(odd);
  ASSERT_LISTS_EQUAL(ref, ifl);
  auto all = []([[maybe_unused]] ValueType value) { return true; };
  ref.remove_if(all);
  ifl.remove_if(all);
  ASSERT_LISTS_EQUAL(ref, ifl);
}

TEST_F(IntrusiveForwardListTest, Remove) {
  Remove<IFLTestValueList>();
  Remove<ConstIFLTestValueList>();
  Remove<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Unique() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 311233774457 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  ref.unique();
  ifl.unique();
  ASSERT_LISTS_EQUAL(ref, ifl);
  std::forward_list<int> check({ 31237457 });
  ASSERT_LISTS_EQUAL(check, ifl);

  auto bin_pred = [](const ValueType& lhs, const ValueType& rhs) {
    return (lhs.value & ~1) == (rhs.value & ~1);
  };
  ref.unique(bin_pred);
  ifl.unique(bin_pred);
  ASSERT_LISTS_EQUAL(ref, ifl);
  check.assign({ 312747 });
  ASSERT_LISTS_EQUAL(check, ifl);
}

TEST_F(IntrusiveForwardListTest, Unique) {
  Unique<IFLTestValueList>();
  Unique<ConstIFLTestValueList>();
  Unique<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Merge() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref1({ 148812 });
  std::vector<std::remove_const_t<ValueType>> storage1(ref1.begin(), ref1.end());
  ListType ifl1(storage1.begin(), storage1.end());
  std::forward_list<int> ref2({ 35679 });
  std::vector<std::remove_const_t<ValueType>> storage2(ref2.begin(), ref2.end());
  ListType ifl2(storage2.begin(), storage2.end());
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  CHECK(std::is_sorted(ref1.begin(), ref1.end()));
  CHECK(std::is_sorted(ref2.begin(), ref2.end()));
  ref1.merge(ref2);
  ifl1.merge(ifl2);
  ASSERT_LISTS_EQUAL(ref1, ifl1);
  ASSERT_LISTS_EQUAL(ref2, ifl2);
  CHECK(ref2.empty());
  std::forward_list<int> check({ 13456788912 });
  ASSERT_LISTS_EQUAL(check, ifl1);
}

TEST_F(IntrusiveForwardListTest, Merge) {
  Merge<IFLTestValueList>();
  Merge<ConstIFLTestValueList>();
  Merge<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Sort1() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 2983741530 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK(!std::is_sorted(ref.begin(), ref.end()));
  ref.sort();
  ifl.sort();
  ASSERT_LISTS_EQUAL(ref, ifl);
  std::forward_list<int> check({ 0123345789 });
  ASSERT_LISTS_EQUAL(check, ifl);
}

TEST_F(IntrusiveForwardListTest, Sort1) {
  Sort1<IFLTestValueList>();
  Sort1<ConstIFLTestValueList>();
  Sort1<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Sort2() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 2983741530 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  auto cmp = [](const ValueType& lhs, const ValueType& rhs) {
    return (lhs.value & ~1) < (rhs.value & ~1);
  };
  CHECK(!std::is_sorted(ref.begin(), ref.end(), cmp));
  ref.sort(cmp);
  ifl.sort(cmp);
  ASSERT_LISTS_EQUAL(ref, ifl);
  std::forward_list<int> check({ 1023345798 });
  ASSERT_LISTS_EQUAL(check, ifl);
}

TEST_F(IntrusiveForwardListTest, Sort2) {
  Sort2<IFLTestValueList>();
  Sort2<ConstIFLTestValueList>();
  Sort2<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::Reverse() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 835413 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);
  CHECK(!std::is_sorted(ref.begin(), ref.end()));
  ref.reverse();
  ifl.reverse();
  ASSERT_LISTS_EQUAL(ref, ifl);
  std::forward_list<int> check({ 314538 });
  ASSERT_LISTS_EQUAL(check, ifl);
}

TEST_F(IntrusiveForwardListTest, Reverse) {
  Reverse<IFLTestValueList>();
  Reverse<ConstIFLTestValueList>();
  Reverse<IFLTestValue2List>();
}

template <typename ListType>
void IntrusiveForwardListTest::ModifyValue() {
  using ValueType = typename ListType::value_type;
  std::forward_list<int> ref({ 3742 });
  std::vector<std::remove_const_t<ValueType>> storage(ref.begin(), ref.end());
  ListType ifl(storage.begin(), storage.end());
  ASSERT_LISTS_EQUAL(ref, ifl);

  auto add1 = [](const ValueType& value) { return value.value + 1; };
  std::transform(ref.begin(), ref.end(), ref.begin(), add1);
  std::transform(ifl.begin(), ifl.end(), ifl.begin(), add1);
  ASSERT_LISTS_EQUAL(ref, ifl);
}

TEST_F(IntrusiveForwardListTest, ModifyValue) {
  ModifyValue<IFLTestValueList>();
  // Does not compile with ConstIFLTestValueList because LHS of the assignment is const.
  // ModifyValue<ConstIFLTestValueList>();
  static_assert(std::is_const_v<ConstIFLTestValueList::iterator::value_type>);
  ModifyValue<IFLTestValue2List>();
}

struct Tag1;
struct Tag2;
struct TwoListsValue : public IntrusiveForwardListNode<TwoListsValue, Tag1>,
                       public IntrusiveForwardListNode<TwoListsValue, Tag2> {
  // Deliberately not explicit.
  TwoListsValue(int v) : value(v) { }  // NOLINT(runtime/explicit)

  int value;
};
using FirstList =
    IntrusiveForwardList<TwoListsValue, IntrusiveForwardListBaseHookTraits<TwoListsValue, Tag1>>;
using SecondList =
    IntrusiveForwardList<TwoListsValue, IntrusiveForwardListBaseHookTraits<TwoListsValue, Tag2>>;

bool operator==(const TwoListsValue& lhs, const TwoListsValue& rhs) {
  return lhs.value == rhs.value;
}

TEST_F(IntrusiveForwardListTest, TwoLists) {
  // Test that a value can be in two lists at the same time and the hooks do not interfere.
  std::vector<TwoListsValue> storage({ 0123456789 });  // storage[i] = i

  std::vector<int> order1({ 3172894065 });
  FirstList list1;
  auto pos1 = list1.before_begin();
  for (size_t idx : order1) {
    pos1 = list1.insert_after(pos1, storage[idx]);
  }

  std::vector<int> order2({ 8516729304 });
  SecondList list2;
  auto pos2 = list2.before_begin();
  for (size_t idx : order2) {
    pos2 = list2.insert_after(pos2, storage[idx]);
  }

  // Using `storage[i] = i`, we can easily compare that nodes of each list are in the right order.
  ASSERT_LISTS_EQUAL(order1, list1);
  ASSERT_LISTS_EQUAL(order2, list2);
}

}  // namespace art

Messung V0.5 in Prozent
C=97 H=92 G=94

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.