To właśnie pojawiło się w kontekście innego pytania .
Wygląda na to, że funkcje składowe w szablonach klas są tworzone tylko wtedy, gdy są używane przez ODR. Czy ktoś mógłby wyjaśnić, co to dokładnie oznacza. Artykuł Wikipedii na temat reguły jednej definicji (ODR) nie wspomina o „ używaniu ODR ”.
Jednak standard definiuje to jako
Zmienna, której nazwa pojawia się jako wyrażenie potencjalnie wartościowane, jest używana jako odr, chyba że jest obiektem, który spełnia wymagania dotyczące pojawienia się w wyrażeniu stałym (5.19), a konwersja lwartość do rwartości (4.1) jest natychmiast stosowana.
w [basic.def.odr].
Edycja: Najwyraźniej jest to zła część, a cały akapit zawiera wiele definicji różnych rzeczy. To może być odpowiednie dla funkcji składowej szablonu klasy:
Nieprzetężona funkcja, której nazwa pojawia się jako potencjalnie ocenione wyrażenie lub element członkowski zestawu funkcji kandydujących, jeśli zostanie wybrana przez rozpoznanie przeciążenia w przypadku odwołania z potencjalnie ocenianego wyrażenia, jest używana przez ODR, chyba że jest to czysta wirtualna funkcja, a jej nazwa nie jest jawnie kwalifikowana.
Nie rozumiem jednak, jak ta reguła działa w wielu jednostkach kompilacji? Czy instancje wszystkich funkcji składowych są tworzone, jeśli jawnie utworzę wystąpienie szablonu klasy?
źródło
Odpowiedzi:
To po prostu dowolna definicja, używana przez standard do określenia, kiedy należy podać definicję jednostki (a nie tylko deklarację). Standard nie mówi tylko „używany”, ponieważ można to interpretować różnie w zależności od kontekstu. A niektóre zastosowania ODR tak naprawdę nie odpowiadają temu, co normalnie kojarzy się z „użyciem”; na przykład funkcja wirtualna jest zawsze używana przez ODR, chyba że jest czysta, nawet jeśli w rzeczywistości nie jest wywoływana nigdzie w programie.
Pełna definicja znajduje się w §3.2 , drugi akapit, chociaż zawiera odniesienia do innych sekcji w celu uzupełnienia definicji.
Jeśli chodzi o szablony, użycie ODR to tylko część pytań; druga część to tworzenie instancji. W szczególności §14.7 dotyczy sytuacji, w których tworzona jest instancja szablonu. Ale oba są powiązane: chociaż tekst w §14.7.1 (niejawna instancja) jest dość długi, podstawową zasadą jest to, że szablon zostanie utworzony tylko wtedy, gdy zostanie użyty, iw tym kontekście użyte oznacza użycie ODR. W związku z tym funkcja składowa szablonu klasy zostanie utworzona tylko wtedy, gdy zostanie wywołana lub jeśli jest wirtualna i zostanie utworzona instancja samej klasy. Sam standard liczy na to w wielu miejscach:
std::list<>::sort
zastosowania<
na poszczególnych elementach, ale możesz utworzyć instancję listy na typie elementu, który nie obsługuje<
, o ile go nie wywołujeszsort
.źródło
W prostych słowach, odr-used oznacza, że coś (zmienna lub funkcja) jest używane w kontekście, w którym musi istnieć definicja tego.
na przykład,
struct F { static const int g_x = 2; }; int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. // so it's OK without the definition of g_x vector<int> vi; vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect // a const lvalue, so it's definition must be present
Uwaga, powyższe push_back przekazane w MSVC 2013, to zachowanie nie jest standardową zgodnością, zarówno gcc 4.8.2, jak i clang 3.8.0 nie powiodły się, komunikat o błędzie to: undefined odwołanie do `K :: g_x '
źródło
vi.push_back( F::g_x );
w C ++?const int&
? Czy statyczny element stałej stałej może być traktowany jako rvalue?push_back
, oczywiście przejdzie. Prawda?operator+
.