[RFC] export Workaround?
-
Mir ist gestern spontan ein Workaround für export bei Templates eingefallen. Getestet hab ich das ganze mit einem gcc 4.1.2.
Erstmal der Code://main.cpp #include "test.hpp" #include <iostream> class tester { int arg_; public: tester(int arg) : arg_(arg) {} void do_it() { std::clog << "Hello World!" << std::endl; ++arg_; } int arg() {return arg_;} }; int main() { test::test test_it; tester obj(2); test_it.test_it(obj); std::clog << obj.arg() << std::endl; return 0; }//test.hpp #ifndef TEST_HPP #define TEST_HPP namespace test { class test { class base { public: virtual ~base() {} virtual void do_it()=0; }; public: test() {} ~test() {} template<typename T> void test_it(T &arg) { class arg_wrapper : public base { public: arg_wrapper(T &arg) : arg_(arg) {} virtual void do_it() {arg_.do_it();} private: T &arg_; }; arg_wrapper wrapper(arg); do_test_it(wrapper); } private: void do_test_it(base &arg); }; } #endif//test.cpp #include "test.hpp" namespace test { void test::do_test_it(base &arg) { arg.do_it(); } }Makefile:
CC=g++ CFLAGS=-O2 -g0 -I/usr/include/boost-1_35 -Wall -Werror -ansi DEPEND=-M LD=g++ LDFLAGS= RM=rm -f OBJ=test.o main.o SRC=test.cpp main.cpp PROG=test all: $(PROG) $(PROG): depend $(OBJ) $(LD) $(LDFLAGS) $(OBJ) -o $(PROG) %.o: %.cpp $(CC) $(CFLAGS) -c $< -o $*.o clean: $(RM) $(PROG) $(OBJ) depend: $(RM) .depend $(CC) $(CFLAGS) $(DEPEND) $(SRC) >.depend include .dependAlso, das ganze funktioniert bei mir mit einem gcc 4.1.2 unter Linux perfekt; ich habe die Implementation von test::test_it praktisch in test.cpp ausgelagert. Der Code mag nicht das Gelbe vom Ei sein, aber ich denke es ist ein guter Workaround.
So, was ich jetzt von euch wissen möchte:
1. Ist das laut C++ Standard legal?
2. Das müsste ja eigentlich gut automatisierbar sein; so könnte man ein export implementieren zum Beispiel, oder?
3. Gibts das schon?Schonmal ein großes Danke

-
Hi,
sorry, ich kann hier überhaupt nicht erkennen, inwieweit das etwas mit dem export von templates zu tun haben soll .... Ich glaube ehrlich gesagt auch nicht, dass es funktioniert.
Bist Du sicher, dass ich das template nutzen könnte, ohne den Code zur Compilezit zu sehen für meine eigenen Klassen nutzen könnte ? .. und zwar inklusive aller Typsicherheit, die mir der Compiler für templates bietet ?Gruß,
Simon2.
-
Die eigentliche Implementation von test_it (also do_test_it) kennt der Compiler nur, wenn er test.cpp kompiliert, aber nicht, wenn main.cpp kompiliert wird. Aber erst, wenn main.cpp kompiliert wird, steht der Typ des Arguments von test_it fest.
Also insofern denke ich schon, dass du das ohne die eigentliche Implementation zu sehen mit einer eigenen Klasse nutzen kannst.
Ob die Typsicherheit genauso gewährleistet ist, kann ich nicht sagen, da müssten Leute her, die etwas mehr von der Materie verstehen ;).
-
Hi,
... allerdings sehe ich nicht, wo Deine ("test"-)Klasse mehr tut als ein schlichtes Funktionstemplate wie:
template<typename T> void test_it(T &arg) { arg.do_it(); }Ja, Du hast den Aufruf der wrapperfunktion einmal (per klassischer virtual function) ausgelagert ... aber das Wesentliche bleibt zur Compilezeit sichtbar: Das, was Dein template mit dem parametrisierenden Typen macht ("
virtual void do_it() {arg_.do_it();}") !Ich würde mal sagen: Ersetzt kein export.

Gruß,
Simon2.
-
Simon2 schrieb:
Hi,
... allerdings sehe ich nicht, wo Deine ("test"-)Klasse mehr tut als ein schlichtes Funktionstemplate wie:
template<typename T> void test_it(T &arg) { arg.do_it(); }Mehr soll sie ja auch nicht tun

Ja, Du hast den Aufruf der wrapperfunktion einmal (per klassischer virtual function) ausgelagert ... aber das Wesentliche bleibt zur Compilezeit sichtbar: Das, was Dein template mit dem parametrisierenden Typen macht ("
virtual void do_it() {arg_.do_it();}") !Ich würde mal sagen: Ersetzt kein export.

OK, in dieser Hinsicht hast du natuerlich Recht. Bleibt trotzdem eine interessante Technik, finde ich

Danke fuer den Kommentar

-
YASC|logged_out schrieb:
Simon2 schrieb:
Hi,
... allerdings sehe ich nicht, wo Deine ("test"-)Klasse mehr tut als ein schlichtes Funktionstemplate wie:
template<typename T> void test_it(T &arg) { arg.do_it(); }Mehr soll sie ja auch nicht tun

... vielleicht habe ic mich ungenau ausgedrückt: Ich sehe nicht, wo "Dein Konstrukt bzgl. Compilezeitunabhängigkeit mehr bietet als ein einfaches Funktionstemplate".
Durch die "virtual-Indirektion" kannst Du zwar zur Compilezeit Deiner "test"-klasse) festlegen, wann, wo, wie Deine Wrapperklassen aufgerufen werden, aber wie diese mit dem parametrisierenden Typen umgehen, kannst Du eben leider nicht vorgeben (bzw. diesen Source bekommt der Anwender trotzdem in die Hand gedrückt).
Dass die Klasse "versteckt" (in private-Section bzw. Funktion) sind, ist ein neckisches Detail ... aber eben dadurch, dass man das jedesmal neu compiliert nur begrenzt ein Schutz gegen Mißbrauch....Nichtsdestotrotz habe ich durch Deinen Entwurf einiges gelernt.
Danke,
Simon2.
-
Simon2 schrieb:
YASC|logged_out schrieb:
Simon2 schrieb:
Hi,
... allerdings sehe ich nicht, wo Deine ("test"-)Klasse mehr tut als ein schlichtes Funktionstemplate wie:
template<typename T> void test_it(T &arg) { arg.do_it(); }Mehr soll sie ja auch nicht tun

... vielleicht habe ic mich ungenau ausgedrückt: Ich sehe nicht, wo "Dein Konstrukt bzgl. Compilezeitunabhängigkeit mehr bietet als ein einfaches Funktionstemplate".
OK, danek für die Klarstellung
Durch die "virtual-Indirektion" kannst Du zwar zur Compilezeit Deiner "test"-klasse) festlegen, wann, wo, wie Deine Wrapperklassen aufgerufen werden, aber wie diese mit dem parametrisierenden Typen umgehen, kannst Du eben leider nicht vorgeben (bzw. diesen Source bekommt der Anwender trotzdem in die Hand gedrückt).
Sollten irgendwelche raffinierten Algorithmen oder so in der Implementation auftauchen, müssen diese aber gerade nicht dem Anwender in die Hand gegeben werden. Das ist in meinem Beispiel zwar nicht der Fall, aber es ist schließlich auch nur ein Minimalbeispiel ;). Was mit den übergebenen Objekten gemacht wird, muss aber trotzdem im Header stehen, da hast du Recht.
Aber auf jeden Fall eine Verbesserung, finde ich.Nichtsdestotrotz habe ich durch Deinen Entwurf einiges gelernt.
Danke
