关于C#:使用带有结构不完整类型错误的模板

using a template with a struct incomplete type error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
#include <map>
using namespace std;

template<typename T>
struct Node
{
    map<string, T> data;
    struct Node* left, * right, * bottom;
    Node(map<string, T> data)
    {
        this->data = data;
        left = right = bottom = NULL;
    }

};


int main()
{
    cout << endl;
   
    map <string, string> test;
    test["walid"] ="walid";
    struct Node* root = new Node(test); #error here
    cout << root->data["walid"];


    cout << endl;


    return 0;
}

有人可以告诉我为什么我会收到不完整的类型错误吗?我正在尝试根据数据使用不同的映射值类型创建节点。


can someone please tell me why I'm getting incomplete type error?

因为您正在尝试创建指向您尚未定义的类型的指针/尝试创建您尚未定义的类型的动态对象。

您还没有定义一个名为 Node 的类型。您已经定义了一个名为 Node 的类模板。您不能拥有 Node* 的原因与不能拥有 std::vector* 的原因相同。这个编译器错误解释了发生了什么:

1
error: template argument required for 'struct Node'

您可以实例化模板以获得一个类,它是一个类型。尖括号语法用于实例化模板,并传递模板参数。示例:

1
Node<std::string>* root = ...

请注意,如果让编译器从初始化器中推断出指针的类型,那么编译器可以隐式推断类模板参数(该语言特性是在 C 17 中引入的):

1
auto* root = new Node(test);

附言如果编译,您的示例会泄漏内存。避免裸拥有指针。更喜欢 RAII 容器和智能指针。不需要时也避免动态分配。


Node 不是类型,而是模板。 Node<string> 是您所追求的类型。

此外,变量声明中的 struct 在 C 中是多余的,因此将该行更改为:

1
Node<string>* root = new Node<string>(test);

以后别忘了delete root;——或者你可以把root设为一个值:

1
Node<string> root{test};

最后,你可以在这里用std::move优化一些东西,比如:

1
2
3
4
5
Node(map<string, T> data)
{
    this->data = data;
    left = right = bottom = NULL;
}

使用初始化列表和 std::move 你可以保存一份可能很昂贵的 data:

1
2
3
Node(map<string, T> d) :
    data{std::move(d)},
    left{nullptr}, right{nullptr}, bottom{nullptr} {}

同样,由于您不再使用 test,您可以将其移至构造函数参数中:

1
Node<string> root{std::move(test)};