Error C2662 - const

Iniciado por digimikeh, 7 Julio 2019, 18:15 PM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh

Hola amigos..

En el siguiente código, si yo quito la palabra const (línea 52) derivada de un template tipo C, el programa corre....


Link -> https://onlinegdb.com/SyW1F9kWS
Hagan clic en Fork para probar el código.

Estuve buscando por què pasa esto, segun el compilador no pudo realizar una conversion de un tipo que no es const a uno que es const...  entiendo que quitando la palabra const se acaba el problema, pero por que?.. y si no deseo retirar la palabra const donde mas debería agregarla para que pueda compilar?... (Pasa que el libro que estudio aparece con const, ero no veo diferencia realmente con lo que tengo).

Gracias.




Bueno, según un usuario de discord, me dijo que las funciones begin() y end() deben ser const también, y efectivamente colocándolas asi compiló correctamente.

Pero es curioso porque en el libro que estudio, dichas funciones no son const..

Ahora mismo estoy investigando por que´.




Si yo coloco las funciones begin() y end() como funciones no miembro, es decir, fuera de la clase o estructura, el compilador no las detecta...

Lnik -> https://onlinegdb.com/SJgL5ayZH


Debe forzosamente ser funciones miembro?

EI: NO HAGAS DOBLE POST NUEVAMENTE, SERA BORRADO.
Dungeons & dragons;
dragons.Attack();

RayR

#1
Lo que pasa es que si tienes un objeto/struct const (o una referencia o puntero a objeto const), sólo puedes invocar a sus funciones miembro que también sean const. Si no fuera así, no habría forma de garantizar que el objeto sea realmente const (piensa, por ejemplo, que podrías llamar a sus "setters", con lo cual estarías modificando alguna de sus variables miembro). Al declarar una función como const, estás indicando que no modificarás ningún miembro del objeto, y el compilador se asegurará de que así sea: si dentro de una función miembro const intentas modificar alguna variable miembro, se producirá un error.

Ahora, cuando tienes algo como esto:

Código (cpp) [Seleccionar]
for (auto i : obj)

y obj hace referencia a un objeto, el "range-based for" internamente llama a obj.begin() y obj.end(), así que si obj es const, esas dos funciones también deben serlo, o el compilador no dejará que sean invocadas.

Loretz

En general necesitas las dos versiones para begin y para end, las const y no const, para que pueda usarse la que corresponda en cada caso.

Por ejemplo, si tienes: definidas las cuatro funciones miembro:
Código (cpp) [Seleccionar]
template <typename T>
    T* s<T>::begin() {
        return elem;
    }

    template <typename T>
    const T* s<T>::begin() const {
        return elem;
    }

    template <typename T>
    T* s<T>::end() {
        return begin() + size;
    }

    template <typename T>
    const T* s<T>::end() const {
        return begin() + size;
    }


Podrás usar tanto
Código (cpp) [Seleccionar]
template <typename C, typename V>
V sum(C& c, V v) {  // c es una referencia no constante
    for (auto a : c) { // usa las versiones no const de begin() y de end()
        v += a;
    }
    return v;
}


como
Código (cpp) [Seleccionar]
template <typename C, typename V>
V sum(const C& c, V v) {  // c es una referencia constante
    for (auto a : c) {          // usa las versiones const de begin() y de end()
        v += a;
    }
    return v;
}

digimikeh

Muy bien, buenísimas explicaciones, me quedó claro, entonces es una regla del compilador todo esto, ahora le hallo sentido...

@Loretz si tienes tu libro a mano, veras que en la pagina 78 se usa la version const, pero en la pagina 77 solo están definidos begin() y end() de forma no constante... entonces supongo que la reseña esta imcompleta... verdad?
Dungeons & dragons;
dragons.Attack();

RayR

Por cierto, respecto a tu segunda pregunta, begin y end no necesariamente debe ser funciones miembro, pero en caso de que sean funciones sueltas, necesitan estar en el mismo namespace que el objeto para que el compilador las encuentre; sin embargo, en ese caso hacer que puedas usarlos con objetos const se complica más, y tendrías que declarar versiones de begin y end que acepten y retornen const, así como una sobrecarga de sólo lectura (const) del operador [].

digimikeh

Asi es, lo he notado, no pude declarar las funciones no miembro como const... pero no me haré problemas al menos por ahora y las declarare como funciones miembro...

saludos.
Dungeons & dragons;
dragons.Attack();