2015-10-31 5 views
1

я могу определения структуры, как это:Как определить самореферентную карту в C++?

struct A{ 
    map<string,A> m; 
}; 

и я могу использовать его как это:

A a; 
a.m["abc"].m["def"]; 

, но я хочу, чтобы использовать его как это:

a["abc"]["def"]; 

это требует a будет map<string,typeof(a)>

, но ic не определите что-то такое, как map<string,map<string,...>>

Это не требует бесконечного пространства, но я не знаю, как определить такую ​​вещь на C++. Как я могу это сделать?

+0

Концептуально, как эта цепочка заканчивается? –

+1

Почему бы не добавить оператор [] в структуру A? – user4581301

+0

@ A.S.H: ему не нужно заканчивать ... можно было просто использовать ключи для представления n-образных деревьев строк. – 6502

ответ

2

Вы не можете. Для самореферентных структур данных в C++ вам нужно использовать указатели.

Даже случай

struct A { 
    map<string, A> m; 
}; 

не является правильным, потому что вы используете тип A в качестве параметра std::map, который не был полностью не определен (он имеет «неполный тип» в этой точке).

Он «работает» в большинстве компиляторов, но формально не является кодом C++.

Однако обратите внимание, что если все, что вам нужно прикован operator[] это легко сделать, если ваша реализация уже принимая map<string, A> члена:

struct A { 
    map<string, A> m; 
    A& operator[](const string& key) { 
     return m[key]; 
    } 
} 

Пример, который компилирует на г ++ и лязгом ++ (но помните, что это НЕ действительный C++):

#include <map> 
#include <string> 
#include <stdio.h> 

struct A { 
    std::map<std::string, A> m; 
    A& operator[](const std::string& x) { return m[x]; } 
}; 

void dump(const A& a, int indent=0) { 
    for (auto& i : a.m) { 
     printf("%*s%s\n", indent, "", i.first.c_str()); 
     dump(i.second, indent+2); 
    } 
} 

int main(int argc, const char *argv[]) { 
    A a; 
    a["1"]["1.1"]; 
    a["1"]["1.2"]; 
    a["1"]["1.3"]; 
    a["2"]["2.1"]; 
    a["2"]["2.2"]; 
    a["3"]["3.1"]["3.1.1"]["3.1.1.1"]; 
    a["4"]; 

    dump(a); 

    return 0; 
}