Jakie jest najlepsze wyjaśnienie słowa kluczowego export w standardzie C++0x?

Jakie jest najlepsze wyjaśnienie słowa kluczowego export w standardzie C++0x?

Chociaż Standard C++ nie ma takich wymagań, niektóre kompilatory wymagają, aby wszystkie szablony funkcji były dostępne w każdej jednostce tłumaczącej, w której są używane. W efekcie dla tych kompilatorów treść funkcji szablonów musi być udostępniona w pliku nagłówkowym . Powtarzając:oznacza to, że te kompilatory nie pozwolą na ich zdefiniowanie w plikach innych niż nagłówkowe, takich jak pliki .cpp. Aby wyjaśnić, w C++ese oznacza to, że:

// ORIGINAL version of xyz.h
template <typename T>
struct xyz
 {
    xyz();
    ~xyz();
 };

NIE byłby zadowolony z tych definicji ctor i dtors:

// ORIGINAL version of xyz.cpp
#include "xyz.h"

template <typename T>
xyz<T>::xyz() {}

template <typename T>
xyz<T>::~xyz() {}

ponieważ używając go:

// main.cpp
#include "xyz.h"

int main()
 {
    xyz<int> xyzint;

    return 0;
 }

spowoduje błąd. Na przykład z Comeau C++ otrzymasz:

ponieważ nie ma użycia ctor ani dtor w xyz.cpp, dlatego nie ma tam żadnych instancji, które musiałyby powstać. Na dobre lub na złe, tak działają szablony.

Jednym ze sposobów na obejście tego jest jawne żądanie utworzenia instancji xyz , w tym przykładzie xyz<int> . W wysiłku brute force można to dodać do xyz.cpp, dodając ten wiersz na końcu:

template xyz<int>;

który żąda (wszystkie) xyz<int> być instancją. To trochę w złym miejscu, ponieważ oznacza to, że za każdym razem, gdy pojawia się nowy typ xyz, plik implementacji xyz.cpp musi zostać zmodyfikowany. Mniej inwazyjnym sposobem uniknięcia tego pliku jest utworzenie innego:

// xyztir.cpp
#include "xyz.cpp" // .cpp file!!!, not .h file!!

template xyz<int>;

Jest to nadal nieco bolesne, ponieważ nadal wymaga ręcznej interwencji za każdym razem, gdy pojawia się nowy xyz. W nietrywialnym programie może to być nieuzasadnione żądanie konserwacji.

Zamiast tego, innym sposobem podejścia do tego jest #include "xyz.cpp" na końcu xyz.h:

// xyz.h

// ... previous content of xyz.h ...

#include "xyz.cpp"

Można oczywiście dosłownie przenieść (wyciąć i wkleić) zawartość xyz.cpp na koniec xyz.h, a tym samym pozbyć się xyz.cpp; jest to kwestia organizacji pliku i na końcu wyniki przetwarzania wstępnego będą takie same, w tym ciała ctor i dtor będą w nagłówku, a zatem zostaną wprowadzone do każdego żądania kompilacji, ponieważ będzie to używać odpowiedniego nagłówka. Tak czy inaczej, ma to taki efekt uboczny, że teraz każdy szablon znajduje się w twoim pliku nagłówkowym. Może to spowolnić kompilację i spowodować rozrost kodu. Jednym ze sposobów podejścia do tego ostatniego jest zadeklarowanie funkcji, o których mowa, w tym przypadku ctor i dtor, jako wbudowanych, więc wymagałoby to zmodyfikowania xyz.cpp w uruchomionym przykładzie.

Nawiasem mówiąc, niektóre kompilatory wymagają również, aby niektóre funkcje były zdefiniowane wewnątrz klasy, a nie poza jedną, więc powyższa konfiguracja musiałaby zostać ulepszona w przypadku tych kompilatorów. Zauważ, że jest to problem kompilatora, a nie standardowego C++, więc nie wszystkie kompilatory tego wymagają. Na przykład Comeau C++ tego nie robi i nie powinien. Sprawdź http://www.comeaucomputing.com/4.0/docs/userman/ati.html, aby uzyskać szczegółowe informacje na temat naszej obecnej konfiguracji. Krótko mówiąc, Comeau C++ obsługuje wiele modeli, w tym jeden, który jest zbliżony do intencji słowa kluczowego eksportu (jako rozszerzenie), a nawet obsługuje sam eksport.

Na koniec zauważ, że słowo kluczowe export C++ ma na celu złagodzenie pierwotnego pytania. Jednak obecnie Comeau C++ jest jedynym kompilatorem, który jest publikowany w celu obsługi eksportu. Zobacz http://www.comeaucomputing.com/4.0/docs/userman/export.html i http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txt, aby uzyskać więcej informacji. Mamy nadzieję, że gdy inne kompilatory osiągną zgodność ze standardem C++, ta sytuacja ulegnie zmianie. W powyższym przykładzie użycie eksportu oznacza powrót do oryginalnego kodu, który spowodował błędy linkera, i dokonanie zmiany:zadeklaruj szablon w xyz.h ze słowem kluczowym export:

// xyz.h

export
// ... ORIGINAL contents of xyz.h ...

ctor i dtor w xyz.cpp zostaną wyeksportowane po prostu na podstawie #includeing xyz.h, co już robi. Tak więc w tym przypadku nie potrzebujesz xyztir.cpp ani żądania utworzenia instancji na końcu xyz.cpp, ani nie potrzebujesz ctor lub dtor ręcznie wprowadzanych do xyz.h. Z wierszem poleceń pokazanym wcześniej, możliwe jest, że kompilator zrobi to wszystko automatycznie.


Zobacz to wyjaśnienie dotyczące jego użycia

Wiele kompilatorów nie obsługuje go, ponieważ jest zbyt nowy lub w przypadku gcc - ponieważ się nie zgadzają.

Ten post opisuje standardową obsługę wielu kompilatorów. Obsługa programu Visual Studio dla nowych standardów C/C++?


Zobacz tutaj i tutaj, jak Herb Sutter traktuje ten temat.

Zasadniczo:eksport został zaimplementowany tylko w jednym kompilatorze - iw tej implementacji eksport faktycznie zwiększa powiązanie między definicją szablonu a deklaracją, podczas gdy jedynym punktem wprowadzenia eksportu było zmniejszenie tego powiązania.

Dlatego większość kompilatorów nie zawraca sobie głowy. Myślałem, że po prostu usunęliby eksport z języka w C++0x, ale nie sądzę, że to zrobili. Może kiedyś będzie dobry sposób na zaimplementowanie eksportu, który ma zamierzone zastosowanie.