Poprawna odpowiedź to Jonathan Wakeley. Zostawię to, ponieważ dostarcza użytecznych informacji dla osób, które mają podobny problem związany z insert
.
Krótka wersja jest taka, że jest to spowodowane problemem w realizacji Biblioteka standardowa używanego przez GCC 4.7.2, która wynikałaby z mylących sformułowań użytych w C++ 11 Standard. Istnieje propozycja zmiany brzmienia, a także poprawka do implementacji w GCC 4.8.
Długa wersja
This GCC bug entry zgłasza bardzo podobny problem, gdzie insert
używany jest zamiast emplace
. LibstdC++ realizacja insert
zgodny ze standardowym, który stanowi o funkcji insert
(konkretnie template <class P> pair<iterator,bool> insert(P&& obj)
):
(§23.5.4.4/5) Uwagi: Podpis ten nie bierze udziału w rozdzielczości przeciążenia chyba P jest niejawnie zamienny do value_type
.
libstdC++ wydaje się być realizowane przy użyciu tego wymogu oświadczenia enable_if
który sprawdza std::is_convertible<>
dla typów zaangażowanych.
Zgłoszony powyżej raport o błędach stwierdza, że naprawdę należało użyć std::is_constructible<>
, a sformułowanie w Standardzie powinno zostać zmienione. To linki do LWG (grupa robocza język) Problem, który proponuje już zmiany w standardowe dla tego (LWG issue #2005, zobacz Portland 2012 wpis, odpowiednią część proponowanej zmiany poniżej):
Zmiana 23.5.4.4 [unord.map.modifers] wokół p. 1, jak wskazano:
template <class P>
pair<iterator, bool> insert(P&& obj);
[...] Uwagi: Podpis ten nie bierze udziału w rozdzielczości przeciążenia chyba P jest
niejawnie zamienny do VALUE_TYPE
std::is_constructible<value_type, P&&>::value
jest prawdą.
Proponowana zmiana stanowi również, że działanie funkcji insert
opisanej powyżej powinna być równoważna emplace(std::forward<P>(obj))
. Dlatego prawdopodobnie można powiedzieć, że problem opisany w pytaniu jest dokładnie tym samym problemem.
I rzeczywiście, proponowane zmiany wydają się być odzwierciedlone w ostatnich GCC 4.8 migawek: Podczas kompilowania kodu z GCC 4.8, kontrola is_convertible
nie jest wykonywane i nie pojawia komunikat o błędzie.
Blisko, ale nie cygar :) LWG 2005 odnosi się tylko do '' emplace' insert' nie, powód program kończy się niepowodzeniem z GCC 4.7.2 jest to, że nie robi kontroli dostępu w ramach odliczenia szablon argument (jak wymagane w C++ 03), więc 'is_constructible' otrzymuje błąd dostępu z powodu prywatnego konstruktora. GCC 4.8 implementuje reguły C++ 11 i sprawdza dostęp podczas dedukcji argumentu szablonu –
Możesz potwierdzić, że różnica nie wynika z jakiejkolwiek zmiany w standardowej bibliotece przez wstępne przetworzenie kodu przy pomocy G ++ 4.7 (więc używa biblioteki z 4.7), a następnie kompilacja to z 4.8, w którym to przypadku program działa, udowadniając, że to nie zmieniona biblioteka, a nie biblioteka –