2009-11-10 8 views
15

Jak mogę uzyskać typ elementów, które są przechowywane przez kontener STL?sprawdź typ elementu w pojemniku STL - C++

+1

Dokładnie, co próbujesz tutaj zrobić? Ponieważ C++ jest statycznie wpisane, powinieneś ogólnie wiedzieć, jakiego typu są te elementy (wektor , na przykład, posiada ints). Jeśli chcesz wyjaśnić, dlaczego nie wiesz, jakie są typy i do czego chcesz ich użyć, to pomożesz odpowiedzieć na pytanie. –

+0

@ David Thornley: 'template void foo (std :: template arg) {/ * Tutaj nie wiemy, jaki jest typ elementów * /}' Myślę, że to dość powszechna sytuacja. – jalf

+0

@Jalf: W tym momencie prawda. Ale w tym momencie foo() jest tylko pojęciem. Ale gdy tylko użyjesz foo(), również znasz typ. –

Odpowiedz

14

przypadku pojemników w ogóle będzie to X::value_type. W przypadku pojemników asocjacyjnych będzie to X::mapped_type (X::value_type odpowiada pair<const Key,T>). Jest to zgodne z Rozdziałem 23 Standardu C++.

Aby sprawdzić, że typy są równe, można użyć boost::is_same.

20
container::value_type 
+0

dobrze, ale już nie mogę porównać dwóch typów wartości zwracanych przez container :: value_type. jakieś sugestie? –

+2

@Patrick: nie można porównać wartości "zwróconych przez value_type", ponieważ value_type jest typem, a nie wartością. Porównanie dwóch typów wartości jest więc operacją statyczną, a nie runtime. W zależności od tego, co próbujesz osiągnąć, możesz zajrzeć do "is_same" w Boost.TypeTraits: http://www.boost.org/doc/libs/1_40_0/libs/type_traits/doc/html/boost_typetraits/reference /is_same.html –

+2

@Patrick: Pytasz o * typ * elementów przechowywanych w wektorze, a nie * wartość * elementów. Możesz porównywać wartości, nie możesz porównywać typów (przynajmniej nie bez wielu trików do metaprogramowania) - może powinieneś wyjaśnić, co próbujesz zrobić. – jalf

0

W jakim sensie? Być może używając RTTI i typeid()?

Prawdopodobnie trzeba użyć kontenera :: ValueType gdzie pojemnik to nazwa kontenera (np std :: vector)

Alek

0

Musisz podać nam więcej kontekstu. Jeśli chcesz, aby wartość była znana podczas kompilacji, więc łatwo ją zmienić, a następnie użyj container::value_type.

typedef vector<int> coordinates; 

coordinates seq; 
fib::value_type elem = seq.back(); // it's easy to change int type 

Jeśli co masz na myśli to, że pojemnik może posiadać różne konkretne typy (pochodne) i chcesz je poznać w czasie wykonywania następnie należy prawdopodobnie ponownie ocenić swoje podejście. W ukrytym programowaniu ukrywanie typu w środowisku wykonawczym jest czasem potężnym podejściem, ponieważ oznacza mniej założeń na temat tego, z czym pracujesz. Możesz oczywiście użyć RTTI, ale prawdopodobnie jest lepszy sposób: potrzebowalibyśmy więcej kontekstu, żeby to powiedzieć.

Jeśli chcesz porównać typy, prawdopodobnie wybierasz ścieżkę środowiska wykonawczego. C++ wspiera polimorfizm, który jest w istocie porównywaniem typów, którymi się opiekujesz - ale wbudowany w język. Chcesz wykonać inny zestaw instrukcji na podstawie typu? Polimorfizm pozwala na wykonanie innej funkcji w zależności od typu obiektu. Nie musisz pisać żadnej dodatkowej linii kodu - pochodzą tylko ze wspólnej bazy.

0

użyć czegoś takiego:

if (typeid(yourVariable)==typeid(YourClass)) //... 

Alek

+0

lub dynamic_cast <> jeśli chcesz przetestować łańcuch dziedziczenia;) –

+0

, ale tylko jeśli twój typ ma metody wirtualne. –

+0

dynamic_cast jest używany na wskaźnikach polimorficznych oczywiście. Nie wspominałem o tym. Masz rację. Dzięki za wskazanie;) –

3

Sprawdzanie, czy dwa typy to samo można osiągnąć w ten sposób (bez RTTI, wartość jest użyteczny w czasie kompilacji):

template <class T, class U> 
struct same_type 
{ 
    static const bool value = false; 
}; 

//specialization for types that are the same 
template <class T> 
struct same_type<T, T> 
{ 
    static const bool value = true; 
}; 

//sample usage: 
template <class FirstContainer, class SecondContainer> 
bool containers_of_same_type(const FirstContainer&, const SecondContainer&) 
{ 
    return same_type< 
     typename FirstContainer::value_type, 
     typename SecondContainer::value_type 
    >::value; 
} 

#include <vector> 
#include <list> 
#include <iostream> 

int main() 
{ 
    std::cout << containers_of_same_type(std::vector<int>(), std::list<int>()); 
    std::cout << containers_of_same_type(std::vector<char>(), std::list<int>()); 
} 

(Zasadniczo działa to w trybie boost::is_same, pomijając obejścia niektórych kompilatorów.)

+0

Wow, to bardzo sprytne –