2011-01-11 10 views
5

Używam metaprogramowania całkiem sporo, ale czasami kombinacja makr c i szablonów po prostu nie wystarcza.Czy istnieją jakieś alternatywy metaprogramowania w C++ oprócz szablonów?

Przypuszczam, że wada potencjalnie być brak kompatybilności między platformami jeśli platforma metaprogramming jest tylko dla, powiedzmy, Linux itp

Więc tak, jest tam coś takiego, dostępny w tej chwili, oprócz szablonów? Wyszukiwarka Google do metaprogramowania jest zdominowana przez metaprogramowanie szablonów, więc trudno go znaleźć teraz.

edycja: oto przykład na temat nad czym pracowałem.

Załóżmy, że mam ogólną klasę do zapisywania/wczytywania plików do i z buforów. Nazwijmy to FilePack.

mam zdefiniować makro, które wygląda

defineFilePack(BaseClass, "code-a") 

To w zasadzie tworzy klasę o nazwie „BaseClassPack”, który jest zdefiniowany jako podklasa. Poniżej jest to.

class FilePack{ 
    public: 
     char * thebuffer; 
     int bufsize; 
     string packcode; 

     // and constructors etc 
     FilePack(const string& thecode, int bufsize); 
     void operator=(FilePack& rhs); 
     void saveToFile(const string& filename); 
     void loadFromFile(const string& filename); 
     // .. and all the function you'd expect to see in a class like this 

}; 

// the person details 

class PersonDetails{ 
    public: 
     solidstring<64> name; 
     int age; 
     DateTime birthday; 
     // .. yada yada yada 
}; 


defineFilePack(PersonDetails, "psd") 

// the above creates the following class 

class PersonDetailsPack : public FilePack{ 
    public: 
     PersonDetailsPack(): 
     FilePack("psd", sizeof(PersonDetails)){ // etc 

     } 

     PersonDetails& get(){ 
     return *(PersonDetails*)getBuffer(); 
     } 

     // and a lot more convenience function 

}; 

Teraz jest rzeczywiście wbudowany sprawdzenie przez konstruktora FilePack że deklarowana kod pasuje do wielkości, przy użyciu globalnego mapę.

W tej chwili jestem zaskoczony, jak to zrobić za pomocą metaprogramowania szablonów, który jest w rzeczywistości odpowiedni dla niego, ponieważ wszystkie te kody pakietów są zadeklarowane w pliku źródłowym. Oczywiście, ktoś może prawdopodobnie stworzyć własny FilePack w czasie wykonywania, ale poza tym chodzi o to.

Inną rzeczą, która może pomóc w metaprogramowaniu, jest obsługa ładowania różnych wersji FilePack. Przypuśćmy, że muszę zaktualizować klasę PersonDetails. Po prostu utworzę nową klasę, użyję metaprogramowania, aby zadeklarować dziedziczenie, i magicznie wymyślę FilePack, aby podczas ładowania starej wersji PersonDetails mógł wywołać funkcję konwersji, lub cokolwiek.

Możesz również komentować tę architekturę i chcę usłyszeć komentarze na jej temat, ale może to być trochę nie na temat?

+0

Czy możesz podać przykład, w którym szablony i makra nie są wystarczające? Byłby to dobry punkt wyjścia do dyskusji. –

+2

@David Rodriguez: Na przykład generowanie kodu, który serializuje klasy w ramach połączenia sieciowego lub ogólnie robi coś dla każdego członka. – 6502

+0

"ale czasami kombinacja makr c i szablonów to po prostu za mało" - czego brakuje/czego brakuje? – Naveen

Odpowiedz

5

Możesz również metaprogramować z preprocesorem.

Można rozważyć użycie preprocesorów specjalnego przeznaczenia do generowania kodu również jako "metaprogramowanie". Następnie możesz dołączyć takie rzeczy jak lex/yacc i Qt MOC.

+0

To, czego szukałem w MOC, szkoda, że ​​to QT:/ale w tej chwili wydaje się być najbardziej praktyczną rzeczą. To chyba jest język na górze języka? – kamziro

+0

Nie widzę powodu, dla którego "szkoda, że ​​to Qt". Uważam, że Qt jest doskonały w tym, do czego jest przeznaczony i nie tylko! –

1

Myślę, że ta praca jest idealna na przykład w Pythonie. Łatwym sposobem jest użycie niestandardowego formatu pliku do opisu sposobu tworzenia klas, a następnie wygenerowanie zarówno implementacji, jak i interfejsu (nawet w wielu językach).

Parsowanie istniejących plików nagłówkowych C++ jest raczej koszmarem z powodu złożonej składni C++ ... (i dlaczego ograniczanie się do tego, co chcesz wyrazić?).

Python jest wieloplatformowy i bardzo ładny język per se ...

Jako przykład poniższe nie jest przykładem „rozszerzonego” C++ użyłem ...

// 
// U8 -> F32 format converter 
// 
// - src(Image:U8) ............ source image 
// - dst(pImage:F32:src) ...... destination image 
// 
ImgFilter u8_to_f32(Image& src, Image& dst) 
{ 
    const double k = 1.0/255; 
    for (int y=0; y<src.h; y++) 
    { 
     unsigned char *rp = src.u8(0, y); 
     float *wp = dst.f32(0, y); 
     for (int x=0,w=src.w; x<w; x++) 
      *wp++ = *rp++ * k; 
    } 
} 

Komentarz powyżej funkcji oraz nazwę/parametry są odczytywane przez skrypt Pythona, który generuje .h dla funkcji, C++ kod, który obsługuje alokacji pamięci, wielkość i zgodnością Format czeki, polecenia argument wiersza analizowania, pomoc online i powiązanie z pythonem. Zasadniczo mogę napisać tylko "mięso" i mieć wygenerowany dla mnie cały zestaw znaków. Skrypt Pythona robiący to jest 200 liniami i biorąc pod uwagę ilość wygenerowanego kodu, płyta C++ dla zaledwie kilku filtrów jest już czymś więcej.

+1

+1, aby przeciwdziałać anonimowemu, niewyjaśnionemu zjazdowi w dół. –

+0

Dawno temu zdecydowałem się zignorować szablony C++, które mają na celu ulepszenie światowej mafii, z którymi nie można logicznie uzasadnić tego, co jest dobre w szablonach (wiele rzeczy), a co nie (wiele innych rzeczy). Moim pierwszym zmartwieniem nie jest walka między niezgodnościami kompilatorów w ciemnych obszarach składni C++ i naprawdę nie tęsknię za tymi czasami. – 6502

+0

Prawdopodobnie zostałeś odrzucony, ponieważ facet przeczytał "ta praca jest idealna dla Pythona", od razu czytając cię jako trolla lub coś podobnego. Podoba mi się to podejście, ale wygląda na to, że wymaga to dużo pracy. To jak tworzenie języka na poziomie C++, który nadal działa z istniejącymi materiałami. To byłoby niesamowite. – kamziro

2

Wewnątrz języka można używać tylko szablonów lub makr do metaprogramu. Możliwości metaprogramowania oferowane przez, powiedzmy, bibliotekę Boost Preprocessor, która implementuje naprawdę niesamowite rzeczy jako makra, są niezwykle potężne.

Jednakże, jeśli chcesz uzyskać trochę więcej, możesz użyć dowolnego języka skryptowego do metaprogramu.

+0

Zawsze zastanawiałem się, jak zwiększa się ich działanie. Nigdy ich tak naprawdę nie używałem, ale wygląda na to, że w nich jest dużo tajemniczych rzeczy. – kamziro

2

Jeśli zdefiniujemy metaprogramowanie jako pisania kodu, który generuje kod, a następnie masz

  • szablony.
  • Preprocesor.
  • Inne przetwarzanie wstępne (zazwyczaj skrypty, ale czasami rozszerzenie kompilatora)
  • Generowanie źródła C++ z kodu C++, kompilacja w locie, ładowanie jako udostępniona biblioteka.
  • Prawdopodobnie, ale to się rozciąga, także generuje kod maszynowy, jak trampoliny.

Myślę, że najbardziej interesujące, że nie jest szablon lub C++ preprocesora jest rozszerzeń, które obsługują język programowania krzyżowego dotyczą, aspect-oriented programming, jak, rejestrowanie połączeń lub metody szeregowania.

Jak pamiętam, ParcPlace stworzył narzędzie do tego?

Hm, to przypomina mi, żebym nie zapomniał tego kiedyś sprawdzić. :-)

Cheers & HTH.,

+0

Zobacz moją odpowiedź na temat systemów transformacji programów, które generalizują programowanie zorientowane na aspekt. Aspekty zapewniają tylko bardzo ograniczone sposoby modyfikacji kodu, a to oznacza, że ​​są jak szablony, które również zapewniają ograniczony (ale inny) sposób. Systemy transformacji programów mogą przeprowadzać dowolne modyfikacje; jesteś ograniczony ambicjami i umiejętnością wyrażania tego, co chcesz robić, a nie tym, co może zrobić konkretna technika metaprogramowania. –

0

Jeśli chcesz wykonać dowolną manipulację kod, chcesz ogólny cel narzędzi meta-programowych, takich jak system transformacji programu. Narzędzia te akceptują kod źródłowy i wykonują dowolne analizy/modyfikacje tego kodu zgodnie z Twoimi potrzebami, wykorzystując technologię podobną do kompilatora.

Nasz DMS Software Reengineering Toolkit jest właśnie takim systemem. Jest sparametryzowany poprzez wyraźny opis języka programowania, który ma być przetwarzany, oraz według zadania, które ma wykonać na kodzie źródłowym. DMS jest unikalny w byciu generycznym w ten sposób (Jackpot to system transformacji tylko dla Javy) i podwójnie unikalny, posiadający solidne C++ Front End, które zostało użyte do zadań transformacji na dużą skalę w produkcyjnym systemie C++.

Dzięki frontowemu interfejsowi DMS może przetwarzać kod źródłowy na abstrakcyjne drzewa składni, budować tabele symboli, wykonywać dopasowania wzorców lub przekształcenia kodu za pomocą wzorów napisanych bezpośrednio w języku C++ i odtwarzać kompilowany kod źródłowy z komentarzami i oryginalnymi formatami literały (uzupełnione liczbą podstawową, itp.). Modyfikacja programu może być dowolną obliczeniową, którą można zdefiniować za pomocą AST. Krótko mówiąc, może to zrobić, z poza tego języka, jakie funkcje metaprogramowania obsługiwane przez język nie mogą zrobić.

Powiązane problemy