2010-01-17 18 views
5

Lo que quiero decir es lo siguiente. Quiero una función de plantilla que tome dos iteradores de vector (o dos punteros a una matriz de doble) y devuelve un doble que de alguna manera está relacionado con los iteradores de vector o los punteros de matriz que paso. Sin embargo, quiero que esto funcione para el tipo doble o int, o cualquier tipo aritmético.En una función de plantilla C++, ¿puedo devolver un tipo de argumento desreferenciado?

creo que no se me permite decir:

template <class T> 
T* func(T Begin, T End) 

T new_variable = Begin + 5; 

return (*new_variable); 
} 

porque el compilador no va a entender lo T * medios. Una solución en la que pensé es tomar lo que estoy tratando de devolver y convertirlo en un tercer argumento:

template <class T> 
void func(T Begin, T End, T* new_variable) 

new_variable = Begin + 5; 

return (*new_variable); 
} 

¿Funcionará? Incluso si es así, ¿hay otra forma de hacer lo que estoy tratando de hacer? (Lo siento si no he sido lo suficientemente claro.)

+3

Tenga en cuenta que el compilador no entiende 'T *' en el tipo de retorno de una función de plantilla; el problema es que el tipo de '* new_variable' no es' T * '. – outis

Respuesta

10

Si desea devolver un doble (es decir, del tipo que se podrían obtener cuando eliminación de referencias), puede utilizar las características de iterador:

template<typename RandomAccessIterator> 
typename std::iterator_traits<RandomAccessIterator>::value_type 
func(RandomAccessIterator a, RandomAccessIterator b) { 
    typedef typename std::iterator_traits<RandomAccessIterator>::value_type 
     value_type; 

    // use value_type now, when you want to save some temporary 
    // value into a local variable, for instance 
    value_type t = value_type(); 
    for(; a != b; ++a) t += *a; 
    return t; 
} 

Estos trabajo para todos los iteradores, incluidos los punteros:

int main() { 
    int d[3] = { 1, 2, 3 }; 
    assert(func(d, d + 3) == 6); 
} 
+0

¡Esto parece ser exactamente lo que necesitaba! Algunos puntos, sin embargo: 1) Creo que se olvidó de iniciar el ciclo for. 2) ¿Está bien cuando usa typedef para nombrar un nuevo tipo para llamarlo value_type? ¿No es esta una palabra clave reservada o algo así? 3) No sabía acerca de iterator_traits porque estoy leyendo Accelerated C++. ¿Puedo obtener más información al respecto en el libro de Josuttis? – jackj

+2

@jackj 1) Puede omitir la sección inicial for-loop si no la necesita. "t" está completamente inicializado al valor predeterminado de value_type (0 para int), 2) Sí, value_type no está reservado. Podemos usarlo para acortar el nombre de tipo largo. 3) sí, el libro de josuttis debería cubrir esto. :) –

+0

¡Guau! Esta es mi primera vez en stackoverflow, pero sé que volveré. Ustedes son increíbles! Gracias un montón. – jackj

3

Bueno, su código parece contradecir lo que describió en el texto. Si T es el tipo de iterador, el resultado del iterador desreferencia (como dijo en el texto) será no si tiene T * (ya que parece creer en el código). T * es algo completamente opuesto: es algo que obtendría si tomara la dirección de su iterador, sin desreferenciarla.

De hecho, no hay forma de expresar el "tipo desreferenciado" usando las características del lenguaje central C++ (tal vez decltype lo hará en el futuro, como en decltype(*T())). La única forma de describir el resultado de la desreferencia del tipo T es usar una solución basada en una biblioteca: rasgos del iterador, como explicó Johannes en su respuesta.

+0

Gracias outis y AndreyT. Tienes razón, el código contradice lo que pensé que estaba pasando. Supongo que me confundí por el hecho de que en C++ el unario * se usa para declarar un puntero, y también para desreferenciar un puntero o un iterador, pero estas dos cosas están separadas. – jackj

+1

@jackj: Esto se debe a que se supone que debes leer la declaración 'T * id' ya que" el tipo de '* id' es' T' ": desafortunadamente provoca errores como' T * a, b; ', que define un 'T *' y un 'T'.También es por qué es 'T id [n]' no 'T [n] id': porque el tipo de' id [n] 'es' T'. –

+1

@jackj: Si tiene problemas con las declaraciones de tipo, intente leer http://unixwiz.net/techtips/reading-cdecl.html o http://www.ericgiguere.com/articles/reading-c-declarations. html. La descripción más simple que he visto (y la razón de la sintaxis) proviene de http://cm.bell-labs.com/cm/cs/who/dmr/chist.html: imagine que la declaración es una expresión cuyo valor es el tipo nombrado al comienzo de la declaración (por ejemplo, para 'T (* d) [2]', piense en '(* d) [1]' como una 'T'). – outis

Cuestiones relacionadas