Portál AbcLinuxu, 11. května 2025 23:36
kontejner
) a v té mám deklarovány další 2 - iterátory (iterator
a const_iterator
).
Pak mám v té šabloně STL-like metody, které vrací iterátory
iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const;Když pak chci použít
begin()
vracející const_iterator
, tak mi GCC řve, že iterator
nelze převést na const_iterator
kontejner<int> k; k.insert(50); k.insert(60); for (kontejner<int>::const_iterator it = k.begin(); it != k.end(); ++it) { // něco }MSVC hlásí ambigous call (nebo tak něco). Dovolil jsem se kouknout do hlavičkového souboru STL a tam je něco podobného, co mám já a tam si kompilátor při použití const_iterator nestěžuje, např. u setu:
set<int> k; k.insert(50); for (set<int>::const_iterator it = k.begin(); it != k.end(); ++it) { // něco }Proč? Proč mu vadí vlastně napsaný a ten v STL mu nevadí, vždyť to je snad to samý ... nebo jsem úplně blbej.
Řešení dotazu:
begin()
vracející const_iterator
stane zbytečnou (protože se použije ta druhá).
To neni tak uplne pravda, verze vracejici const_iterator
je deklarovana jako const
, takze bude pouzita u konstatniho kontejneru.
begin()
je const
a druhá ne. Jakmile to const
odstraníte, překladač vám vynadá, že to nejde overloadnout.
const
a přiřazuju to do const_iterator
... Jak je možné, že když použiju např. set
z STL, tak to funguje, když to v podstatě dělá to samé?
iterator
a ten se následně automaticky přetypuje na const_iterator
. V tomhle smyslu vám to bude fungovat taky, pokud to přetypování umožníte.
Muzete si vynutit zavolani const
metody. Nekam pred cyklus dejte const kontejner<int>& ck = k;
a pak piste nasledujici:
for (kontejner<int>::const_iterator it = ck.begin(); it != ck.end(); ++it)
Uprime receno nevim, cemu se s panem Kubeckem divite, takhle se to normalne dela a ve standardu je u kontejneru receno, ze iterator
musi byt konvertibilni na const_iterator
.
Predevsim, pokud by verze s const
byla (po pridani konverze interator -> const_iterator
) zbytecna, tak byste ji mohl odstranit. Jenze kdyz tam nebude, tak si na konstatnim kontejneru nezavolate metodu begin()
, coz je, jak jiste uznate, u kontejneru nikoliv zanedbatelny nedostatek. Ergo zbytecna neni.
Tak to jsem se asi prehledl. Jaky ze byl ten kontext, ve kterem normalni kontejner nepotrebuje konstatni begin()
metody?
Kdyz uz jsme se tak pekne rozhovorili... z tonu vaseho prispevku mam pocit, ze znate nejake reseni, ktere neni postavene na hlavu a ve kterem se begin() const
nestane zbytecnym. Mohl byste alespon naznacit?
cbegin()
a cend()
, které jsou AFAIK součástí návrhu C++0x.
A čemu tím v daném případě pomůžete? cbegin()
a cend()
má pomoci tam, kde typ iterátoru není znám (tzn. v parametrech šablonových funkcí a auto proměnných), ale to tady nenastává. Tzn. s cbegin
můžu napsat:
std::search(cow_sequence.cbegin(), cow_sequence.cend(), // kompilátore, tady nedělej kopii COW sekvence
needle.begin(), needle.end());
Místo abych psal ekvivalentní
std::search(const_cast<const COW_SEQ&>(cow_sequence).begin(), const_cast<const COW_SEQ&>(cow_sequence).end(), // kompilátore, tady nedělej kopii COW sekvence
needle.begin(), needle.end());
MMCH, v C++ lze v jistém smyslu overloadovat podle návratového typu
No vidite, to neni spatny napad. Na druhou stranu, pokud tomu vytvoru budete chtit rikat kontejner a povolit jeho obecnejsi vyuziti, tak se reseni s konstruktorem nevyhnete. Konec koncu, v navrhu C++0x pozadavek na existenci konverze z iterator
na const_iterator
zustava.
Vysvětlení je asi v této části hlavičkového souboru:
// _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 103. set::iterator is required to be modifiable, // but this allows modification of keys. typedef typename _Rep_type::const_iterator iterator; typedef typename _Rep_type::const_iterator const_iterator;
Chápu-li to dobře, jde o workaround na známou chybu gcc implementace standardní C++ knihovny.
Are Set Iterators Mutable or Immutable?
Mimochodem, v puvodni STL od SGI byly const_iterator
a iterator
pro set
(a dalsi "Simple Associative Container") zadefinovany jako identickeho typu.
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.