我最近将自己的自定义地图类实现为我的C-runtime独立项目的std :: map替换。我知道它可能不如std :: map那么高效,但它可以达到目的。
这是包含所需结构对和节点的类的方式(我删除了大部分与我的问题无关的函数):
template< class T, class U >
class Map;
template< class T, class U >
struct Pair
{
T first;
U second;
};
template< class T, class U >
class Node
{
friend class Map<T, U>;
public:
T first;
U second;
protected:
Node<T, U>* pParent;
Node<T, U>* pLeft;
Node<T, U>* pRight;
public:
Node(T SetFirst,
U SetSecond,
Node<T, U>* pSetParent)
{
this->first = SetFirst;
this->second = SetSecond;
this->pParent = pSetParent;
}
};
template< class T, class U >
class Map
{
private:
Node<T, U>* pRoot,
*pCurrentNode;
private:
template< typename N >
static N Insert(const T& SetFirst,
const U& SetSecond,
Node<T, U>*& Leaf)
{
if (!Leaf)
{
Leaf = new Node<T, U>(SetFirst,
SetSecond,
nullptr);
Leaf->pLeft = nullptr;
Leaf->pRight = nullptr;
return Leaf;
}
else if (SetFirst < Leaf->first)
{
if (Leaf->pLeft != nullptr)
return Insert<N>(SetFirst,
SetSecond,
Leaf->pLeft);
else
{
Leaf->pLeft = new Node<T, U>(SetFirst,
SetSecond,
Leaf);
Leaf->pLeft->pLeft = nullptr;
Leaf->pLeft->pRight = nullptr;
return Leaf->pLeft;
}
}
else
{
if (Leaf->pRight != nullptr)
return Insert<N>(SetFirst,
SetSecond,
Leaf->pRight);
else
{
Leaf->pRight = new Node<T, U>(SetFirst,
SetSecond,
Leaf);
Leaf->pRight->pLeft = nullptr;
Leaf->pRight->pRight = nullptr;
return Leaf->pRight;
}
}
}
public:
Map()
{
this->pRoot = nullptr;
this->pCurrentNode = nullptr;
}
Map(const Map& SetMap)
{
this->pRoot = nullptr;
this->pCurrentNode = nullptr;
this->operator=(SetMap);
}
Map& operator=(Map& SetMap)
{
this->Clear();
if (!SetMap.Empty())
{
for (auto it = SetMap.Begin(); it != nullptr; it = SetMap.Next())
this->Insert(it->first,
it->second,
this->pRoot);
}
return *this;
}
};
因为我的项目是独立于C运行时的,所以我必须负责初始化静态变量,就像我自己在我的项目中使用的一些Map对象一样,所以我这样做就像例如 &#34; Keys = Map();&#34;。 在编译该代码时,它给了我一个错误C2783基本上说&#34;模板参数为&#34; N&#34;无法推断出#34; (我将这些错误翻译成英文,因为我的Visual Studio设置为德语)。 过了一会儿,我看到我没有为operator =中的插入调用指定任何N,所以我开始考虑为什么我甚至需要N并决定将它从函数中删除它以及在类中调用Insert的所有地方。 完成后,Insert函数看起来像这样:
static Node<T, U>* Insert(const T& SetFirst,
const U& SetSecond,
Node<T, U>* Leaf)
{
if (!Leaf)
{
Leaf = new Node<T, U>(SetFirst,
SetSecond,
nullptr);
Leaf->pLeft = nullptr;
Leaf->pRight = nullptr;
return Leaf;
}
else if (SetFirst < Leaf->first)
{
if (Leaf->pLeft != nullptr)
return Insert(SetFirst,
SetSecond,
Leaf->pLeft);
else
{
Leaf->pLeft = new Node<T, U>(SetFirst,
SetSecond,
Leaf);
Leaf->pLeft->pLeft = nullptr;
Leaf->pLeft->pRight = nullptr;
return Leaf->pLeft;
}
}
else
{
if (Leaf->pRight != nullptr)
return Insert(SetFirst,
SetSecond,
Leaf->pRight);
else
{
Leaf->pRight = new Node<T, U>(SetFirst,
SetSecond,
Leaf);
Leaf->pRight->pLeft = nullptr;
Leaf->pRight->pRight = nullptr;
return Leaf->pRight;
}
}
}
然而,在编译之后,我确实不再得到编译器错误,而是“#34;警告C4239非标准扩展&#34;参数&#34;转换自&#34; Map&amp;&#34;&#34;多次出现在输出窗口中,点击它时会将我重定向到代码行,例如&#34; TestMap = Map();&#34; (这个显然只是我添加到我的项目中的代码,用于测试与此问题相关的事情)并且在运行它时我的程序崩溃了。 我班上究竟出了什么问题,我真的需要那个&#34; N&#34;插入中的模板还是可以以其他方式解决?