C++ 我的代码在哪里不符合键和值类型的规范?
任务描述C++ 我的代码在哪里不符合键和值类型的规范?,c++,c++17,C++,C++17,任务描述 interval\u map是一种数据结构,可有效地将K类型键的间隔与V类型值关联起来。您的任务是实现此数据结构的assign member功能,如下所述 interval\u map是在std::map之上实现的。如果您不完全确定哪些函数 STD::MAP提供了它们所做的以及它们提供的保证,我们这里提供了C++标准的摘录。(最后) std::map中的每个键值对(k,v)表示值v与std::map中从k(包括)到下一个键(不包括)的间隔相关联 示例:std::map(0,'A'),(
interval\u map
是一种数据结构,可有效地将K类型键的间隔与V类型值关联起来。您的任务是实现此数据结构的assign member功能,如下所述
interval\u map
是在std::map
之上实现的。如果您不完全确定哪些函数<代码> STD::MAP<代码>提供了它们所做的以及它们提供的保证,我们这里提供了C++标准的摘录。(最后)
std::map
中的每个键值对(k,v)表示值v与std::map
中从k(包括)到下一个键(不包括)的间隔相关联
示例:std::map(0,'A'),(3,'B'),(5,'A')
表示映射
- 0->“A”
- 1->“A”
- 2->“A”
- 3->“B”
- 4->“B”
- 5->“A”
- 6->“A”
- 7->“A”
数值限制::max()
std::map
中的表示必须是规范的,也就是说,连续的map条目不能具有相同的值:…(0,'A'),(3,'A'),…
。最初,K的整个范围与给定的初始值相关联,传递给interval_map数据结构的构造函数
下面是我的assign()
:(其余代码是默认的)
哦,那个烦人的编程练习,你们不是签署了保密协议不披露吗 我认为错误信息并不完全正确。但这一小段代码会告诉您,您的代码是不正确的:
interval_map<uint8_t, std::string> moo("A");
moo.assign(1, 15, "B");
std::cout << moo[255];
区间图moo(“A”);
moo.转让(1,15,“B”);
std::cout您要求您的类型是默认可构造的:
std::pair<K,V> beginExtra;
std::pair<K,V> endExtra;
std::pair beginExtra;
std::对endExtra;
这可能是抱怨的根源。正如其他人所说,代码中的问题是假设K,V都可以默认构造。当您测试一个不可默认构造的键类型时,这一点就变得很清楚了(请参阅下面的我的测试)
“std::pair::pair”:没有合适的默认构造函数可用
这是我的实现,通过了正确性检查,但没有通过运行时复杂性检查。我看不出如何删除N个键,但保持复杂度O(Logn),考虑下面的合法场景:
分配前
“A”百万次间隔C'....A'
分配新间隔后,覆盖以前的间隔:
“A”……”D’……………………”A'
我确信擦除N个节点至少需要O(N)个时间,因为单独为每个节点释放内存是线性的。无论采用何种智能方式,在新开始和新结束之间删除节点都是线性的。另一种等效的方法是提取节点并更改其密钥;但是,这只会将多余的键移向末端,而不是中间
可能正确的答案是在新添加的成员函数中的某个地方-map::extract或map::merge。如果std::map的声明允许异构查找(使用专门设计的“range key”类型的equal_range),那么只需一次调用就可以找到开始和结束插入位置。然而,这对线性O(N)擦除部分没有帮助
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <map>
#include <limits>
template<typename K, typename V>
class interval_map {
public:
std::map<K, V> m_map;
// constructor associates whole range of K with val by inserting (K_min, val)
// into the map
interval_map(V const& val) {
m_map.insert(m_map.end(), std::make_pair(std::numeric_limits<K>::lowest(), val));
}
// Assign value val to interval [keyBegin, keyEnd).
// Overwrite previous values in this interval.
// Conforming to the C++ Standard Library conventions, the interval
// includes keyBegin, but excludes keyEnd.
// If !( keyBegin < keyEnd ), this designates an empty interval,
// and assign must do nothing.
void assign(K const& keyBegin, K const& keyEnd, V const& val) {
if (!(keyBegin < keyEnd))
return;
typename std::map<K, V>::iterator iterBegin; /*The new begin with val, can be begin()*/
typename std::map<K, V>::iterator iterEnd; /*the new end of val, can be end()*/
auto lowerKeyBegin = m_map.lower_bound(keyBegin); //either end() or some iter whose key is not less than keyBegin. [1st O(logN)]
auto upperKeyEnd = m_map.upper_bound(keyEnd); //some iter where keyEnd < key, or end() [2nd O(logN)]
auto prevKeyEnd = std::prev(upperKeyEnd);
/*
The next interval of the new interval starts at keyEnd if the previous value at keyEnd differed from val
*/
if (!(prevKeyEnd->second == val))
{
// prevKeyEnd is either less than the new end we are inserting, or the same (no update to avoid copying from erased node)
if (!(prevKeyEnd->first < keyEnd) && !(keyEnd < prevKeyEnd->first))
iterEnd = prevKeyEnd;
else
iterEnd = m_map.insert_or_assign(upperKeyEnd, keyEnd, prevKeyEnd->second);
}
else
{
iterEnd = upperKeyEnd;
}
/*
The new interval starts at keyBegin if the would-be previous interval has a different value.
Previous interval is either a key in the map less than keyBegin, or non-existent when lower_bound is m_map.begin()
The new interval's start is merged with previous interval, if the previous interval has the same value.
*/
if (lowerKeyBegin != m_map.begin())
{
auto prevIter = std::prev(lowerKeyBegin); //safe when end(), because we always have at least one value
if (!(prevIter->second == val))
{
iterBegin = m_map.insert_or_assign(lowerKeyBegin, keyBegin, val);
}
else iterBegin = prevIter;
}
else
{
iterBegin = m_map.insert_or_assign(lowerKeyBegin, keyBegin, val);
}
/*
Erase all keys between the new begin and end (excluding) so that there is only one value after iterBegin
This is fine when iterEnd is end()
*/
{
auto nextIterOfBegin = std::next(iterBegin);//somehow msvc doesn't support if-initialization
if (nextIterOfBegin != m_map.end())
{
//I would be very interested in a smarter way to get rid of this part without additional storage ...
m_map.erase(nextIterOfBegin, iterEnd);
}
}
////debug - check canonical
//for (auto iter = m_map.begin(); iter != m_map.end(); ++iter)
//{
// auto next = std::next(iter);
// if (next != m_map.end() && iter->second == next->second)
// {
// throw;
// }
//}
}
// look-up of the value associated with key
V const& operator[](K const& key) const {
return (--m_map.upper_bound(key))->second;
}
};
// Many solutions we receive are incorrect. Consider using a randomized test
// to discover the cases that your implementation does not handle correctly.
// We recommend to implement a test function that tests the functionality of
// the interval_map, for example using a map of unsigned int intervals to char.
struct TestKeyType
{
unsigned int val;
constexpr TestKeyType(unsigned int val) : val(val) {}
constexpr bool operator<(const TestKeyType& other) const { return val < other.val; }
};
namespace std {
template<> class numeric_limits<TestKeyType> {
public:
static constexpr TestKeyType lowest() { return TestKeyType(numeric_limits<unsigned int>::lowest()); }
//static constexpr TestKeyType lowest() { return TestKeyType(-250); }
};
}
using TestValueType = char;
struct TestFloatKeyType
{
float val;
TestFloatKeyType() = default;
TestFloatKeyType(float val) : val(val) {}
bool operator< (TestFloatKeyType other) const
{
return other.val - val > 1.e-4f;
}
};
namespace std {
template<> class numeric_limits<TestFloatKeyType> {
public:
static TestFloatKeyType lowest() { return TestFloatKeyType(numeric_limits<float>::lowest()); }
};
}
TEST_CASE("EmptyRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 3, 'B');
REQUIRE(m.m_map.count(3) == 0);
m.assign(3, 2, 'B');
REQUIRE(m.m_map.count(2) == 0);
REQUIRE(m.m_map.count(3) == 0);
}
TEST_CASE("TrivialRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 10, 'B');
REQUIRE(m[0] == 'A');
for (int i = 1; i < 10; i++)
{
REQUIRE(m[i] == 'B');
}
REQUIRE(m[10] == 'A');
}
TEST_CASE("TrivialTwoRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 3, 'B');
m.assign(6, 8, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
REQUIRE(m[6] == 'C');
REQUIRE(m[7] == 'C');
REQUIRE(m[8] == 'A');
}
TEST_CASE("OverwriteLowest")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(std::numeric_limits<TestKeyType>::lowest(), 10000, 'B');
REQUIRE(m[0] == 'B');
REQUIRE(m[9999] == 'B');
REQUIRE(m[10000] == 'A');
}
TEST_CASE("Merge")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(std::numeric_limits<TestKeyType>::lowest(), 10, 'B');
m.assign(10, 20, 'B');
REQUIRE(m[0] == 'B');
REQUIRE(m[10] == 'B');
REQUIRE(m[19] == 'B');
REQUIRE(m[20] == 'A');
}
TEST_CASE("FloatKey")
{
interval_map<TestFloatKeyType, TestValueType> m('A');
m.assign(1.f, 5.f, 'B');
REQUIRE(m[0.f] == 'A');
REQUIRE(m[.999999999f] == 'B');
REQUIRE(m[1.f] == 'B');
REQUIRE(m[4.999f] == 'B');
REQUIRE(m[5.f] == 'A');
}
TEST_CASE("OverlappingRangeComplete")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 5, 'B');
m.assign(1, 6, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'C');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'C');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeInner")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 6, 'C');
m.assign(3, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'C');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeSmallToLarge")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(3, 6, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'C');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeLargeToSmall")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 6, 'C');
m.assign(1, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("ExtendingRangeBegin")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 5, 'B');
m.assign(1, 4, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("ExtendingRangeEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(3, 6, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'B');
REQUIRE(m[6] == 'A');
}
TEST_CASE("ExtendingRangeBothBeginEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(2, 3, 'B');
m.assign(1, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("OverwriteEndValueSafety")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(2, 5, 'B');
m.assign(5, 8, 'C');
m.assign(4, 5, 'A');
}
TEST_CASE("ReusingExistingRangeBothBeginEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(2, 3, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("ReusingEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(4, 6, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("RestoringInitial")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(1, 5, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'A');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("RestoringInitial2")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(0, 7, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'A');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("VeryComplex")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 6, 'B');
m.assign(2, 5, 'C');
m.assign(4, 7, 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
REQUIRE(m[6] == 'A');
REQUIRE(m[7] == 'A');
}
#定义CATCH_CONFIG_MAIN
#包括“catch.hpp”
#包括
#包括
模板
类区间映射{
公众:
std::map mu map;
//构造函数通过插入(K_min,val)将整个K范围与val相关联
//进入地图
区间图(V常数和val){
m_map.insert(m_map.end(),std::make_pair(std::numeric_limits::lowest(),val));
}
//将值val分配给间隔[keyBegin,keyEnd]。
//覆盖此间隔中以前的值。
/符合C++标准库约定,间隔
//包括keyBegin,但不包括keyEnd。
//如果!(keyBeginsecond==val))
{
//prevKeyEnd小于我们插入的新端点,或者相同(无更新以避免从已擦除的节点复制)
如果(!(prevKeyEnd->firstfirst))
iterEnd=prevKeyEnd;
其他的
iterEnd=m_映射。插入_或_赋值(upperKeyEnd、keyEnd、prevKeyEnd->second);
}
其他的
{
iterEnd=upperKeyEnd;
}
/*
如果之前的间隔具有不同的值,则新间隔从keyBegin开始。
上一个间隔是映射中小于keyBegin的键,或者在下限为m_map.begin()时不存在
如果上一个间隔具有相同的值,则新间隔的开始与上一个间隔合并。
*/
if(lowerKeyBegi
std::pair<K,V> beginExtra;
std::pair<K,V> endExtra;
'std::pair<K,V>::pair': no appropriate default constructor available
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <map>
#include <limits>
template<typename K, typename V>
class interval_map {
public:
std::map<K, V> m_map;
// constructor associates whole range of K with val by inserting (K_min, val)
// into the map
interval_map(V const& val) {
m_map.insert(m_map.end(), std::make_pair(std::numeric_limits<K>::lowest(), val));
}
// Assign value val to interval [keyBegin, keyEnd).
// Overwrite previous values in this interval.
// Conforming to the C++ Standard Library conventions, the interval
// includes keyBegin, but excludes keyEnd.
// If !( keyBegin < keyEnd ), this designates an empty interval,
// and assign must do nothing.
void assign(K const& keyBegin, K const& keyEnd, V const& val) {
if (!(keyBegin < keyEnd))
return;
typename std::map<K, V>::iterator iterBegin; /*The new begin with val, can be begin()*/
typename std::map<K, V>::iterator iterEnd; /*the new end of val, can be end()*/
auto lowerKeyBegin = m_map.lower_bound(keyBegin); //either end() or some iter whose key is not less than keyBegin. [1st O(logN)]
auto upperKeyEnd = m_map.upper_bound(keyEnd); //some iter where keyEnd < key, or end() [2nd O(logN)]
auto prevKeyEnd = std::prev(upperKeyEnd);
/*
The next interval of the new interval starts at keyEnd if the previous value at keyEnd differed from val
*/
if (!(prevKeyEnd->second == val))
{
// prevKeyEnd is either less than the new end we are inserting, or the same (no update to avoid copying from erased node)
if (!(prevKeyEnd->first < keyEnd) && !(keyEnd < prevKeyEnd->first))
iterEnd = prevKeyEnd;
else
iterEnd = m_map.insert_or_assign(upperKeyEnd, keyEnd, prevKeyEnd->second);
}
else
{
iterEnd = upperKeyEnd;
}
/*
The new interval starts at keyBegin if the would-be previous interval has a different value.
Previous interval is either a key in the map less than keyBegin, or non-existent when lower_bound is m_map.begin()
The new interval's start is merged with previous interval, if the previous interval has the same value.
*/
if (lowerKeyBegin != m_map.begin())
{
auto prevIter = std::prev(lowerKeyBegin); //safe when end(), because we always have at least one value
if (!(prevIter->second == val))
{
iterBegin = m_map.insert_or_assign(lowerKeyBegin, keyBegin, val);
}
else iterBegin = prevIter;
}
else
{
iterBegin = m_map.insert_or_assign(lowerKeyBegin, keyBegin, val);
}
/*
Erase all keys between the new begin and end (excluding) so that there is only one value after iterBegin
This is fine when iterEnd is end()
*/
{
auto nextIterOfBegin = std::next(iterBegin);//somehow msvc doesn't support if-initialization
if (nextIterOfBegin != m_map.end())
{
//I would be very interested in a smarter way to get rid of this part without additional storage ...
m_map.erase(nextIterOfBegin, iterEnd);
}
}
////debug - check canonical
//for (auto iter = m_map.begin(); iter != m_map.end(); ++iter)
//{
// auto next = std::next(iter);
// if (next != m_map.end() && iter->second == next->second)
// {
// throw;
// }
//}
}
// look-up of the value associated with key
V const& operator[](K const& key) const {
return (--m_map.upper_bound(key))->second;
}
};
// Many solutions we receive are incorrect. Consider using a randomized test
// to discover the cases that your implementation does not handle correctly.
// We recommend to implement a test function that tests the functionality of
// the interval_map, for example using a map of unsigned int intervals to char.
struct TestKeyType
{
unsigned int val;
constexpr TestKeyType(unsigned int val) : val(val) {}
constexpr bool operator<(const TestKeyType& other) const { return val < other.val; }
};
namespace std {
template<> class numeric_limits<TestKeyType> {
public:
static constexpr TestKeyType lowest() { return TestKeyType(numeric_limits<unsigned int>::lowest()); }
//static constexpr TestKeyType lowest() { return TestKeyType(-250); }
};
}
using TestValueType = char;
struct TestFloatKeyType
{
float val;
TestFloatKeyType() = default;
TestFloatKeyType(float val) : val(val) {}
bool operator< (TestFloatKeyType other) const
{
return other.val - val > 1.e-4f;
}
};
namespace std {
template<> class numeric_limits<TestFloatKeyType> {
public:
static TestFloatKeyType lowest() { return TestFloatKeyType(numeric_limits<float>::lowest()); }
};
}
TEST_CASE("EmptyRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 3, 'B');
REQUIRE(m.m_map.count(3) == 0);
m.assign(3, 2, 'B');
REQUIRE(m.m_map.count(2) == 0);
REQUIRE(m.m_map.count(3) == 0);
}
TEST_CASE("TrivialRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 10, 'B');
REQUIRE(m[0] == 'A');
for (int i = 1; i < 10; i++)
{
REQUIRE(m[i] == 'B');
}
REQUIRE(m[10] == 'A');
}
TEST_CASE("TrivialTwoRange")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 3, 'B');
m.assign(6, 8, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
REQUIRE(m[6] == 'C');
REQUIRE(m[7] == 'C');
REQUIRE(m[8] == 'A');
}
TEST_CASE("OverwriteLowest")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(std::numeric_limits<TestKeyType>::lowest(), 10000, 'B');
REQUIRE(m[0] == 'B');
REQUIRE(m[9999] == 'B');
REQUIRE(m[10000] == 'A');
}
TEST_CASE("Merge")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(std::numeric_limits<TestKeyType>::lowest(), 10, 'B');
m.assign(10, 20, 'B');
REQUIRE(m[0] == 'B');
REQUIRE(m[10] == 'B');
REQUIRE(m[19] == 'B');
REQUIRE(m[20] == 'A');
}
TEST_CASE("FloatKey")
{
interval_map<TestFloatKeyType, TestValueType> m('A');
m.assign(1.f, 5.f, 'B');
REQUIRE(m[0.f] == 'A');
REQUIRE(m[.999999999f] == 'B');
REQUIRE(m[1.f] == 'B');
REQUIRE(m[4.999f] == 'B');
REQUIRE(m[5.f] == 'A');
}
TEST_CASE("OverlappingRangeComplete")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 5, 'B');
m.assign(1, 6, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'C');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'C');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeInner")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 6, 'C');
m.assign(3, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'C');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeSmallToLarge")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(3, 6, 'C');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'C');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("OverlappingRangeLargeToSmall")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 6, 'C');
m.assign(1, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'C');
REQUIRE(m[6] == 'A');
}
TEST_CASE("ExtendingRangeBegin")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 5, 'B');
m.assign(1, 4, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("ExtendingRangeEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(3, 6, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'B');
REQUIRE(m[6] == 'A');
}
TEST_CASE("ExtendingRangeBothBeginEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(2, 3, 'B');
m.assign(1, 5, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("OverwriteEndValueSafety")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(2, 5, 'B');
m.assign(5, 8, 'C');
m.assign(4, 5, 'A');
}
TEST_CASE("ReusingExistingRangeBothBeginEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(2, 3, 'B');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'B');
REQUIRE(m[5] == 'A');
}
TEST_CASE("ReusingEnd")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(4, 6, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'B');
REQUIRE(m[2] == 'B');
REQUIRE(m[3] == 'B');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("RestoringInitial")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(1, 5, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'A');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("RestoringInitial2")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(1, 5, 'B');
m.assign(0, 7, 'A');
REQUIRE(m[0] == 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'A');
REQUIRE(m[3] == 'A');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
}
TEST_CASE("VeryComplex")
{
interval_map<TestKeyType, TestValueType> m('A');
m.assign(3, 6, 'B');
m.assign(2, 5, 'C');
m.assign(4, 7, 'A');
REQUIRE(m[1] == 'A');
REQUIRE(m[2] == 'C');
REQUIRE(m[3] == 'C');
REQUIRE(m[4] == 'A');
REQUIRE(m[5] == 'A');
REQUIRE(m[6] == 'A');
REQUIRE(m[7] == 'A');
}
if (not (keyBegin < keyEnd) )
return;
auto beginLowerBound = m_map.lower_bound(keyBegin);
auto endLowerBound = m_map.lower_bound(keyEnd);
std::optional<std::pair<K,V>> additionalElement;
if (endLowerBound == m_map.end() || keyEnd < endLowerBound->first)
additionalElement = std::pair(keyEnd, operator[]( keyEnd ));
else if (beginLowerBound == m_map.end() || keyBegin < beginLowerBound->first)
additionalElement = std::pair(keyEnd, operator[]( keyBegin ));
if (beginLowerBound != m_map.end())
m_map.erase(beginLowerBound, endLowerBound);
m_map.insert(std::pair(keyBegin, val));
if (additionalElement)
m_map.insert(additionalElement.value());