2009-07-10 15 views
14

tengo una clase¿Es posible obtener el tipo de valor de un iterador arbitrario (C++)?

template <typename Iterator, typename Value> 
class Foo { 
public: 
    Foo(const Iterator& it) { ... } 
    ... 
private: 
    map<Value, int> m_; 
    } 
}; 

¿Hay alguna manera de deshacerse de valor de la plantilla? El iterador puede o no ser un iterador de STL, pero se garantiza que * es de tipo Valor.

Sé acerca de iterator_traits<T>::value_type para los iteradores de STL, pero me pregunto si hay alguna forma de obtener el tipo de valor automáticamente para un tipo de iterador arbitrario.

Un truco que estoy pensando - por ejemplo, tenemos una clase de ayuda

template <typename Iterator, typename Value> 
class Bar { 
public: 
    Bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 
    ... 
}; 

Entonces, si creamos una instancia como Bar Bar (que, * él), el tipo de valor se dará a conocer en el interior bar. Pero no puedo encontrar una buena manera de combinar Bar con Foo.

Respuesta

18

Cualquier iterador debería proporcionar iterator_traits<Iterator>::value_type. Si no lo hace, entonces no es un iterador. ISO C++ 2003 24.3.1 [lib.iterator.traits] "rasgos Iterator":

para implementar algoritmos sólo en términos de iteradores, a menudo es necesario determinar el valor y diferencia tipos que corresponden a un tipo de iterador particular . En consecuencia, es requiere que si Iterator es el tipo de un iterador, los tipos

iterator_traits<Iterator>::difference_type 
iterator_traits<Iterator>::value_type 
iterator_traits<Iterator>::iterator_category 

ser definido como el tipo del iterador diferencia, tipo de valor y categoría iterador, respectivamente.

Aparte de eso, no hay una forma general de obtener un tipo de expresión arbitraria de C++. C++ 0x lo rectificará al proporcionar decltype.

+0

Gracias, la referencia al estándar ISO C++ es útil. –

1

Lo sentimos. La forma correcta de deshacerse de Value es usar iterator_traits como sugirió.

Si su iterador no STL es un puntero desnudo, entonces obtiene los iterator_traits correctos typedefs de forma gratuita. De lo contrario, la clase de iterador no STL debe definir los typedefs correctos.

Consulte el iterator traits documentation para obtener más información.

1

En cuanto a obtener el tipo de valor del iterador las respuestas anteriores eran correctas.

Pero hay más. El truco en el que estás pensando no funcionaría con la clase. Si Bar era una función como:

template <typename Iterator, typename Value> 
void bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 

a continuación Tipo de deducción funcionaría para bar(it, *it) y que tendría el tipo de valor en el interior de bar. (Pero tenga en cuenta que para usar este truco aún tendría que tener un iterador sin referencias que no siempre es bueno, ¿cómo lidiar con la secuencia vacía?)

Utilizar una clase Bar que tendría que proporcionar los argumentos de plantilla Iterator y Value manualmente ya que no se requiere ningún tipo de deducción para las clases y el uso de Bar(it, *it) haría ninguna compilación.

+0

¡Gracias! Pensé lo mismo sobre el uso de la barra como función, pero pensé que tal vez me estaba perdiendo algo. –

Cuestiones relacionadas