Poniższy kod nie kompiluje w GCC 4.7.2 lub Clang 3.2:Nie można skopiować std :: wektor <std :: function <void()>> za pomocą jednolitej inicjalizacji. Czy to jest poprawne?
#include <vector>
#include <functional>
int main()
{
std::vector<std::function<void()>> a;
std::vector<std::function<void()>> b{a};
}
Problem jest, że kompilator będzie próbował tworzyć b stosując initializer_list, gdy wyraźnie powinno być po prostu wywołanie konstruktora kopii. Jednak wydaje się, że to pożądane zachowanie, ponieważ standard mówi, że konstruktory initializer_list powinny mieć pierwszeństwo.
Kod ten działałby dobrze dla innych std :: vector, ale dla funkcji std :: kompilator nie może wiedzieć, czy chcesz konstruktor initializer_list czy inny.
Nie wygląda na to, że istnieje sposób obejścia tego, a jeśli tak jest, to nigdy nie można użyć jednolitej inicjalizacji w kodzie szablonowym. Co byłoby wielkim wstydem.
Z drugiej strony Visual Studio (2012 CTP w listopadzie) nie narzeka na to. Jednak obsługa initializer_list nie jest w tym momencie zbyt dobra, więc może to być błąd.
Dzięki za odpowiedź. Łącze LWG 2132 tak naprawdę mówi o problemie, który jest podobny, ale inny, że tak właśnie jest, aby rozwiązać ten problem. Oznacza to, że problem zostanie rozwiązany tylko dla std :: function, a nie dla innych typów z szablonowymi konstruktorami. Myślę, że moja nowa reguła dla jednolitej inicjalizacji to "użyj jej wszędzie, gdzie możesz, chyba że obiekt ma konstruktor initializer_list." Używaj go tylko, jeśli chcesz tego konstruktora."Co oznacza także, że nie można go używać w szablonowym kodzie." –
Wolę regułę "nie pisz nieograniczonych szablonów konstruktorów, które umożliwiają niejawną konwersję z dowolnego typu." Jeśli nie tworzysz takich typów, to wygrywasz " • powodują problemy dla osób, które próbują użyć twojego typu z klasami, które mają konstruktory listy inicjalizacyjnej. Standardowa biblioteka nie przestrzegała tej reguły, ale jest to naprawione dla 'std :: function'. –