2010-01-28 111 views
5

我認爲元編程非常酷。特別是,我喜歡lisp宏。但是,我認爲C++模板吸引因爲:
1.他們減慢編譯時間(即使預編譯的頭文件,如果你包含任何他的STL的東西,最終是50MB大)。
2.它們給出了可怕的編譯器/語法錯誤,這些錯誤是不合理的
3.它們並不是因爲複雜的元編程而被設計出來的(對於素數/生成模擬器的錯誤,圖靈完成是件大事那天)。儘管如此,C++元編程是否還有一個不錯的選擇?像C++模板的替代品?

* .m - >元編譯器 - > * .cpp - > g ++ - >可執行文件?

編輯:

我沿着線thikning「自定義代碼代腳本。」 我只是想知道是否有一套非常好的一套。

+1

你想生成或計算出什麼樣的東西?結構?直線功能?意大利麪代碼?狀態機? – Potatoswatter 2010-01-28 03:15:38

回答

1

如果您使用C++,我認爲您唯一可行的選擇是直接preprocessor macros或自定義code-generation

您描述的工作流程基本上等於某種形式的代碼生成,您可以將.m文件預處理爲可編譯的C++代碼。 SWIG是一個很好的例子。我個人很喜歡用Python編寫代碼生成器,但我認爲任何腳本語言都會一樣好。一個可能會使用的包是cog,來自我們自己的Ned Batchelder :)

7

我不確定這是應該需要的,我使用了代碼生成器來生成C++代碼。 尤其是python獵豹。您基本上將直接的Python代碼嵌入到您的C++代碼中,並通過獵豹預處理器運行。與使用模板或C++預處理器相比,它允許執行相當複雜的計算,並且您可以獲得所有的Python庫和擴展。另一方面,如果出現錯誤,它會使調試更加困難。如果您有興趣,我可以提供一些示例和Emacs模式來編輯獵豹C++程序。

如果您需要的功能不夠強大,並且只想保留在C++ C中,請參閱boost預處理器,here。這需要一點時間來適應它,但可以使生活很容易,當重複代碼是參與

沒關係,我粘貼獵豹例子,給我幾分鐘:

#if defined (__INTEL_COMPILER) 
#pragma vector aligned 
#endif 
     for(int a = 0; a < $N; ++a) { 
      /// for functions in block 
%for ii, (fi,fj) in enumerate(fb) 
%set i = ii + ifb 
/// can also use (ix,iy,iz)=fi[0:2], need to clean up when not lazy 
%set ix = fi[0] 
%set iy = fi[1] 
%set iz = fi[2] 
%set jx = fj[0] 
%set jy = fj[1] 
%set jz = fj[2] 
      q$(i) += Ix(a,$(ix),$(jx))*Iy(a,$(iy),$(jy))*Iz(a,$(iz),$(jz)); 
%end for 
      /// end for functions in block 
     } 

產生(運行後cheetah ...

#if defined (__INTEL_COMPILER) 
#pragma vector aligned 
#endif 
     for(int a = 0; a < 6; ++a) { 
      q0 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,0,0); 
      q1 += Ix(a,1,1)*Iy(a,0,0)*Iz(a,0,0); 
      q2 += Ix(a,0,1)*Iy(a,1,0)*Iz(a,0,0); 
      q3 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,1,0); 
      q4 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,0,0); 
      q5 += Ix(a,1,0)*Iy(a,0,1)*Iz(a,0,0); 
      q6 += Ix(a,0,0)*Iy(a,1,1)*Iz(a,0,0); 
      q7 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,1,0); 
      q8 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,0,1); 
      q9 += Ix(a,1,0)*Iy(a,0,0)*Iz(a,0,1); 
     } 

這是一個常規的C++代碼

線開始%是由預獵豹解釋爲Python語句處理器。 ///是獵豹的評論。默認使用#作爲python語句,但是我改變它們以避免與C預處理器指令衝突。必須使用%end來終止python塊。以$開頭的C++代碼中的變量被python變量替代。

你想使用boost預處理器的例子嗎?

+0

請詳細解釋。 – anon 2010-01-28 01:20:37

+0

我一直在做類似於這個使用Mako的東西;我找到了這個,同時尋找更爲標準的選擇。 – 2010-08-19 19:55:54

0

代碼生成是最好的答案...

您還應該看看Linux內核如何鏈接列表。

Linux Kernel Linked List Explained

的基本思路是不是具有嵌入在一些結構的類型(比如用next和prev指針,一個典型的列表實現),你必須嵌入到結構中的內核列表結構.. 。心情彎曲,但看看這篇文章...我從來沒有想過類型安全的泛型是可能的C,直到我看到這....

+0

除此之外,您的示例不是類型安全的,它是無法使用的。 – rlbond 2010-01-28 01:50:53

+0

好的,好吧,不存在任何鑄件...... :) – dicroce 2010-01-28 15:09:36

+0

鑄件隱藏在一些宏的後面。然而對於那些以類型安全的方式做這種事情很困難或者不可能的C來說,這種技術是非常有用的。 Windows也有類似的宏('CONTAINING_RECORD()')進行鏈表操作。考慮到C的侷限性,這是一種很好的技術。現在我已經學到了一個有用的新術語:「類型不經意」。 – 2010-01-28 17:29:23

2

大多數人堅持試圖從他們最喜歡的語言內部元程序。由於模板元編程的原因,C++被視爲典型例子。雖然它的作品,它是痛苦和笨拙的。我發現它告訴人們在Stroustrop將它添加到語言之後發現它具有圖靈功能;儘管我懷疑他現在會抱怨它,但我認爲他甚至不認爲它會像他這樣做。

但是大多數編程語言沒有元編程功能。 (或者它們可能具有弱或笨拙的能力:)

解決此問題的方法是使用 program transformation tools以外的進行元編程。這些工具可以解析源代碼,並對其進行任意轉換(這就是元編程無論如何),然後吐出修改過的程序。

如果您有一個通用的程序轉換系統,可以解析任意語言,那麼您可以使用任何您喜歡的語言進行元編程。 請參閱我們的DMS Software Reengineering Toolkit,該工具對於C,C++,Java,C#,COBOL,PHP和許多其他編程語言具有健壯的前端,並且已用於所有這些元編程。

此方法非常有用,因爲它提供了一種常規的方法論方法,可以爲任何您想要操作的語言提供元編程方法。您不必等待語言設計人員和實施人員實施,也不必忍受他們可以想象或實際執行的限制,或者支付所需的所有反射數據的運行時間空間/時間價格以支持它。

儘管TM是圖靈功能,程序轉換比C++模板元編程更強大!原因是TM可以從模板生成任意代碼,但不能修改非模板代碼。如果你堅持,程序轉換可以模擬TM,並且至少也是如此強大,但它也可以對非模板代碼進行任意更改。因此,嚴格來說更強大。

就像TM一樣,使用程序轉換需要一些努力來學習和應用。但能夠以任意方式操作程序似乎非常有用。 (我們已經對使用DMS的超大型C++應用程序進行了體系結構重組,但TM不能做到這一點)。

+0

另請參閱http://stackoverflow.com/a/21358087/120163 – 2014-01-26 01:01:20