me Merily experimentando con los nuevos tipos de retorno de arrastre, donde conectó un problema con este código (simplificado)arrastran tipos de retorno, decltype y const-dad
#include <list>
class MyContainer{
std::list<int> ints;
auto begin() -> decltype(ints.begin())
{
return ints.begin();
}
auto begin() const -> decltype(ints.begin())
{
return ints.begin();
}
};
Ignorar el hecho de cómo inútil este código es . La parte importante es el error del compilador genera cuando se utiliza gcc 4.6.1 (con -std=c++0x
bandera):
In member function 'std::list<int>::iterator MyContainer::begin() const':
error: could not convert '((const MyContainer*)this)->MyContainer::ints.std::list<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>, std::list<_Tp, _Alloc>::const_iterator = std::_List_const_iterator<int>]()' from 'std::list<int>::const_iterator {aka std::_List_const_iterator<int>}' to 'std::list<int>::iterator {aka std::_List_iterator<int>}'
En caso de que usted no está de fan de error relacionado con las plantillas, el cuento es que en el cuerpo de la const
versión de MyContainer::begin
, la expresión ints.begin()
devuelve un valor de tipo std::list<int>::const_iterator
(desde ints
es const
en ese contexto). Sin embargo, decltype(ints.begin())
produce el tipo std::list<int>::iterator
, es decir, decltype
ignora el calificador const
del método begin
al decidir el tipo de expresión. Como era de esperar, el resultado es un conflicto de tipos.
Esto me parece ser un error en el compilador de GCC. Solo tendría sentido para decltype
cumplir con el calificador const
y generar el tipo const_iterator
. ¿Alguien puede confirmar o negar (quizás incluso explicar) esto? Tal vez estoy pasando por alto algo en la mecánica de decltype
, pero este parece un escenario bastante sencillo.
Nota: hasta donde puedo decir, el mismo comportamiento se aplica no solo para std::list<int>
, sino para cualquier tipo con funciones de miembro sobrecargadas en const
-ness que devuelven tipos incompatibles.
Compila sin error con una instantánea reciente de gcc 4.7.0. Hasta entonces, supongo que estás atrapado con 'ints.cbegin()' – Cubbi
Por supuesto, en un caso tan trivial no era un obstáculo serio, pero es importante que gcc lo haga bien para todos los casos no triviales (I también quería asegurarme de que * I * lo entendiera bien; no deseo utilizar funciones que no entiendo). –