2015-03-09 5 views
31

Rozważmy następujące deklaracje:Jak uzyskać wymiary (zagnieżdżenie) zagnieżdżonego wektora (NIE rozmiaru)?

vector<vector<int> > v2d; 
vector<vector<vector<string>> > v3d; 

Jak mogę dowiedzieć się „wymiarowości” wektorów w kolejnym kodzie? Na przykład 2 dla v2d i 3 dla v3d?

+9

C++ jest mocno napisany, więc znasz już wymiar dzięki temu, że możesz z niego korzystać. 2d zawsze będzie dwuwymiarowym wektorem w tym samym zakresie. – Rado

+2

Czy możesz podać kontekst, w którym nie bylibyście świadomi tych informacji? – Galik

+6

@Galik Templates. – emlai

Odpowiedz

57

Coś na tych liniach:

template<class Y> 
struct s 
{ 
    enum {dims = 0}; 
}; 

template<class Y> 
struct s<std::vector<Y>> 
{ 
    enum {dims = s<Y>::dims + 1}; 
}; 

Wtedy na przykład

std::vector<std::vector<double> > x; 
int n = s<decltype(x)>::dims; /*n will be 2 in this case*/ 

Posiada atrakcyjną właściwość, że wszystkie oceny są w momencie kompilacji.

+2

Preferuję to rozwiązanie, jest ono oceniane podczas kompilacji i jest bardziej podobne do sposobu "type_traits". –

+2

można dodać wsparcie dla niestandardowych podzielników także –

+1

Użyj następującego jeśli chcesz to nazwać jak funkcja: 'szablonu constexpr size_t Rank (const T &) { powrócić s :: przyciemnia; } 'as' s :: dims' jest nieco brzydki. Będzie generował ten sam kod w jedną stronę (np. 'Movl $ 3,% esi') –

18

Można zrobić coś takiego:

template<typename T> 
int getDims(const T& vec) 
{ 
    return 0; 
} 
template<typename T> 
int getDims(const vector<T>& vec) 
{ 
    return getDims(T{})+1; 
} 

Sidenote: Ilość ta jest czasami nazywana "rank".

+4

To tworzy grupę bezużytecznych tymczasowości; może można go poprawić –

+1

i wykonuje obliczenia w czasie wykonywania –

+0

@MattMcNabb, każdy rozsądny kompilator powinien być w stanie wstawić to do stałej. – imallett