¿Cuáles son algunos límites estilísticos razonables en la inferencia de tipos?

7

C ++ 0x agrega un soporte de inferencia de tipos bastante completo. Estoy muy tentado de usarlo en todas partes para evitar repeticiones indebidas, pero me pregunto si eliminar la información explícita de tipo por todas partes es una buena idea. Considere este ejemplo bastante artificial:

Foo.h :

#include <set>

class Foo {
private:

    static std::set<Foo*> instances;

public:

    Foo();
    ~Foo();

    // What does it return? Who cares! Just forward it!
    static decltype(instances.begin()) begin() {
        return instances.begin();
    }

    static decltype(instances.end()) end() {
        return instances.end();
    }

};

Foo.cpp :

#include <Foo.h>
#include <Bar.h>

// The type need only be specified in one location!
// But I do have to open the header to find out what it actually is.
decltype(Foo::instances) Foo::instances;

Foo() {

    // What is the type of x?
    auto x = Bar::get_something();

    // What does do_something() return?
    auto y = x.do_something(*this);

    // Well, it's convertible to bool somehow...
    if (!y) throw "a constant, old school";

    instances.insert(this);

}

~Foo() {
    instances.erase(this);
}

¿Diría que esto es razonable o es completamente ridículo? Después de todo, especialmente si está acostumbrado a desarrollar en un lenguaje dinámico, realmente no necesita cuidarse tanto de los tipos de cosas, y puede confiar en que el compilador detectará Abusos del tipo de sistema. Pero para aquellos de ustedes que dependen del soporte del editor para las firmas de métodos, no tienen suerte, por lo que el uso de este estilo en una interfaz de biblioteca es probablemente una mala práctica.

Encuentro que escribir cosas con todos los tipos posibles implícitos en realidad hace que mi código sea mucho más fácil de seguir, porque elimina casi todo el desorden habitual de C ++. Su millaje puede, por supuesto, variar, y eso es lo que me interesa escuchar. ¿Cuáles son las ventajas y desventajas específicas del uso radical de la inferencia de tipos?

    
pregunta Jon Purdy 07.01.2011 - 07:35

3 respuestas

4

Al ser principalmente un programador de Python, comparto la mentalidad de que el programador no necesita saber el tipo exacto. En el caso de C ++, especialmente cuando se trata de plantillas con plantilla con plantilla con plantilla ... Por supuesto que no es porque ofrezco escritura estática (no lo creo, considero a Haskell una de las mejores cosas desde que se cortó el pan, en parte debido a su escritura estática), sino porque no me importa el tipo exacto. Por qué, no se demuestra bien con ejemplos que usan nombres como foo o get_stuff() . Así que vamos a elegir algo más cercano a la realidad:

auto users = get_users();
vector<decltype(users[0])> blocked_users;
/* I'm not a C++ guru, much less C++0x so forgive me if type
   inference and foreach must be combined differently */
for (auto user : users) {
    if (check_name(user.name)) blocked_users.push_back(user)
}

No es una anotación de tipo único, pero está perfectamente claro lo que hace, ¿verdad? A este código no le importa cuál es el tipo de users , solo necesita un rango para iterar sobre el que contiene elementos con un name que se puede alimentar a check_name . Nada mas. A nadie le importan los 100 caracteres de los nombres de tipo que tendrías que escribir de otra manera.

Lo mismo se aplica a la mayoría de los códigos con nombres significativos. El ejemplo de la pregunta no está claro, pero tampoco lo sería con nombres de tipo explícitos, porque ni el contexto ni los identificadores dan ninguna indicación de lo que está sucediendo. Utilice identificadores significativos, y el código se puede entender independientemente de las anotaciones de tipo explícitas.

    
respondido por el user7043 07.01.2011 - 09:54
2

La razón por la que trajeron inferencia fue para evitar que las personas escriban código como:

foo().bar().baz().etc();

Cuando podrías escribir:

Foo f = foo();
Bar b = f.bar();
...

Excepto que Foo sería un tipo de plantilla larga, por lo que es mejor escribir:

auto f = foo();
auto b = f.bar();
...

Entonces, como regla general, si el uso automático hace que escribas un código como el anterior en lugar de un código similar al primer ejemplo, entonces, por todos los medios, úsalo. De lo contrario, siga agregando definiciones explícitas.

    
respondido por el dan_waterworth 07.01.2011 - 09:14
2

Hay buenas razones para no usar siempre la inferencia de tipos. Haskell tiene inferencia de tipos, pero de todos modos generalmente declaro explícitamente los tipos de funciones. Eso es parcialmente un resultado de mi estilo de desarrollo. Yo declaro la función primero:

myFunction :: [Int] -> Int
myFunction xs = undefined
A continuación, escribiré el código que usa esa función y haré una compilación para asegurarme de que escriba las comprobaciones. Una vez que escriba las comprobaciones, seguiré adelante con la implementación.

La otra razón para declarar tipos de funciones es que las declaraciones pueden servir como documentación adicional. Que esta documentación se verifique en cada compilación es una ventaja.

    
respondido por el Larry Coleman 07.01.2011 - 20:49

Lea otras preguntas en las etiquetas