ero Merily sperimentando con i nuovi tipi di ritorno finale, in cui mi ha colpito un problema con questo codice (semplificato)tipi restituiti trailing, decltype e const-ness
#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();
}
};
ignorano il fatto di come inutile questo codice è . La parte importante è l'errore del compilatore generato quando si usa GCC 4.6.1 (con -std=c++0x
bandiera):
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>}'
Nel caso in cui non sei di fan di errore che coinvolgono modelli, il racconto è che nel corpo del const
versione MyContainer::begin
, l'espressione ints.begin()
restituisce un valore di tipo std::list<int>::const_iterator
(poiché ints
è const
in tale contesto). Tuttavia, decltype(ints.begin())
produce il tipo std::list<int>::iterator
, ad esempio decltype
ignora il qualificatore const
nel metodo begin
quando si decide il tipo di espressione. Non sorprende che un conflitto di tipi sia il risultato.
Questo mi sembra un bug nel compilatore GCC. Avrebbe senso solo per decltype
onorare il qualificatore const
e produrre il tipo const_iterator
. Qualcuno può confermare o negare (forse anche spiegare) questo? Forse sto trascurando qualcosa nella meccanica di decltype
, ma questo sembra uno scenario piuttosto semplice.
Nota: per quanto posso dire, lo stesso comportamento vale non solo per std::list<int>
, ma per qualsiasi tipo con funzioni membro sovraccarico su const
-ness che restituiscono tipi incompatibili.
Compila senza errori con l'istantanea recente di gcc 4.7.0. Fino ad allora, suppongo che tu sia bloccato con 'ints.cbegin()' – Cubbi
Ovviamente, in un caso così banale questo non era un ostacolo serio, ma è importante che gcc lo faccia bene per tutti i casi non banali (I volevo anche assicurarmi che * I * abbia ragione - non desidero usare caratteristiche che non capisco). –