2010-01-28 44 views
5

Tôi nghĩ rằng lập trình meta rất hay. Đặc biệt, tôi thích các macro lisp.Lựa chọn thay thế cho mẫu C++?

Tuy nhiên, tôi nghĩ rằng mẫu C++ hút vì:
1. chúng làm chậm thời gian biên dịch (ngay cả với các tiêu đề được biên dịch trước mà kết thúc là 50MB lớn nếu bạn bao gồm bất kỳ công cụ STL nào).
2. chúng cung cấp cho các lỗi biên dịch/cú pháp khủng khiếp là trực quan
3. chúng không được dành cho lập trình meta phức tạp ngay từ đầu (tạo lỗi comipler cho số nguyên tố/hiển thị các mẫu được hoàn chỉnh là một thỏa thuận lớn trong ngày).

Có nói tất cả điều đó, có một lựa chọn thay thế cho lập trình meta C++ không? một cái gì đó như

* .m -> trình biên dịch meta -> * .cpp -> g ++ -> thực thi?

CHỈNH SỬA:

Tôi đang phát triển dọc theo dòng "tập lệnh thế hệ mã tùy chỉnh". Tôi chỉ tự hỏi nếu có một bộ thực sự tốt trong số họ ra khỏi đó.

+1

Những loại điều bạn đang cố gắng để tạo ra hoặc tính toán? Cấu trúc? Chức năng đường thẳng? Mã spaghetti? Máy nhà nước? – Potatoswatter

Trả lời

1

Nếu bạn đang sử dụng C++, tôi nghĩ các lựa chọn thay thế khả thi duy nhất của bạn là thẳng preprocessor macros hoặc tùy chỉnh code-generation.

Luồng công việc mà bạn mô tả về cơ bản sẽ tính đến một số dạng tạo mã nơi bạn sẽ xử lý trước tệp .m của mình thành mã C++ có thể nén. SWIG là một ví dụ thực sự tốt về một dự án thực hiện điều này.

Cá nhân, tôi đã thành công lớn khi viết trình tạo mã bằng Python nhưng tôi nghĩ rằng bất kỳ ngôn ngữ kịch bản nào cũng sẽ tốt. Một gói có thể được sử dụng là cog từ Ned Batchelder :)

7

Tôi không chắc chắn đây là những gì cần, tôi đã sử dụng trình tạo mã để tạo mã C++. Đặc biệt, cheetah python. Về cơ bản bạn nhúng mã python thẳng vào bên trong mã C++ và chạy qua cheetah preprocessor.it cho phép thực hiện các phép tính phức tạp dễ dàng hơn nhiều so với sử dụng các mẫu hoặc tiền xử lý C++, cộng với bạn nhận tất cả các thư viện và phần mở rộng python. mặt khác, nó làm cho việc gỡ lỗi trở nên khó khăn hơn nếu có điều gì đó sai. Nếu bạn quan tâm, tôi có thể cung cấp một số ví dụ và chế độ Emacs để chỉnh sửa các chương trình C++ cheetah.

Nếu bạn cần thứ gì đó ít mạnh mẽ hơn và chỉ muốn ở trong C++ C, hãy xem bộ tiền xử lý tăng cường, here. Phải mất một chút thời gian để làm quen với nó, nhưng có thể làm cho cuộc sống thực sự dễ dàng khi mã lặp đi lặp lại có liên quan đến

okay, tôi đang dán dụ cheetah, cho tôi một vài phút:

#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 
     } 

sản xuất (sau khi chạy 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); 
     } 

mà là một C thường xuyên ++ mã

dòng bắt đầu bằng% được hiểu là báo cáo python bởi cheetah trước bộ xử lý. /// là các bình luận cheetah. Mặc định sử dụng # như câu lệnh python, nhưng tôi đã thay đổi chúng để tránh va chạm với các chỉ thị tiền xử lý C. %end phải được sử dụng để chấm dứt các khối python. Các biến trong mã C++ bắt đầu bằng $ được thay thế bằng các biến python.

Bạn có muốn các ví dụ sử dụng bộ tiền xử lý tăng cường không?

+0

Vui lòng giải thích thêm. – anon

+0

Tôi đã làm một cái gì đó tương tự như thế này bằng cách sử dụng Mako; Tôi tìm thấy điều này trong khi tìm kiếm một giải pháp thay thế tiêu chuẩn hơn. –

0

Tạo mã là câu trả lời hay nhất ...

Bạn cũng nên xem cách hạt nhân Linux thực hiện danh sách được liên kết.

Linux Kernel Linked List Explained

Ý tưởng cơ bản là thay vì có loại của bạn nhúng vào trong một số struct (nói với con trỏ tới và trước, đối với một danh sách thực hiện điển hình), bạn có struct danh sách kernel nhúng trong struct CỦA BẠN .. Loại tâm uốn, nhưng hãy kiểm tra các bài viết ... Tôi không bao giờ nghĩ loại generics an toàn đã có thể trong C cho đến khi tôi thấy điều này ....

+0

Ngoại trừ trường hợp đó, ví dụ của bạn không an toàn cho loại hình, loại này không biết gì. – rlbond

+0

ok, tốt, không có đúc liên quan anyway ... :) – dicroce

+0

đúc được ẩn đằng sau một số macro. Tuy nhiên đối với C, nơi khó khăn hoặc có thể không làm được điều này một cách an toàn, kỹ thuật này khá hữu ích. Windows cũng có các macro tương tự ('CONTAINING_RECORD()') cho thao tác danh sách liên kết. Đó là một kỹ thuật tốt đẹp cho những hạn chế của C. Và bây giờ tôi đã học được một thuật ngữ mới hữu ích: "loại không biết gì". –

2

Hầu hết mọi người nhấn mạnh vào việc cố gắng metaprogram từ bên trong ngôn ngữ yêu thích của họ. C++ được giữ như là ví dụ tinh túy vì lập trình meta mẫu. Trong khi nó hoạt động, nó là đau đớn và vụng về. Tôi thấy nó nói cho mọi người biết rằng nó có khả năng Turing, sau khi Stroustrop thêm nó vào ngôn ngữ; Tôi thậm chí không nghĩ rằng anh ấy nghĩ nó sẽ hoàn toàn giống như cách anh ấy làm, mặc dù tôi nghi ngờ anh ấy sẽ phàn nàn về nó ngay bây giờ.

Nhưng hầu hết các ngôn ngữ lập trình không có cơ sở lập trình meta. (Hoặc chúng có thể có khả năng yếu hoặc vụng về :)

Cách xung quanh việc này là thực hiện lập trình meta từ bên ngoài ngôn ngữ, sử dụng program transformation tools. Các công cụ như vậy có thể phân tích cú pháp mã nguồn, và thực hiện các phép biến đổi tùy ý trên nó (đó là những gì metaprogramming làm anyway) và sau đó nhổ chương trình sửa đổi.

Nếu bạn có một hệ thống chuyển đổi chương trình mục đích chung, có thể phân tích ngôn ngữ tùy ý, bạn có thể thực hiện lập trình meta trên/với bất kỳ ngôn ngữ nào bạn muốn. Xem DMS Software Reengineering Toolkit của chúng tôi cho một công cụ như vậy, có giao diện người dùng mạnh mẽ cho C, C++, Java, C#, COBOL, PHP và một số ngôn ngữ lập trình khác và đã được sử dụng để lập trình meta trên tất cả các công cụ này.

Cách tiếp cận này hữu ích vì nó cung cấp cách tiếp cận thường xuyên, phương pháp luận để cung cấp phương pháp lập trình meta cho bất kỳ ngôn ngữ nào bạn muốn thao tác. Và bạn không phải chờ các nhà thiết kế và người triển khai ngôn ngữ triển khai, bạn cũng không phải sống với những hạn chế về những gì họ có thể tưởng tượng hoặc thực sự triển khai, hoặc trả giá thời gian/thời gian chạy của tất cả dữ liệu phản chiếu đó để hỗ trợ nó.

Và chuyển đổi chương trình mạnh hơn so với lập trình meta mẫu C++, mặc dù TM là Turing có khả năng! Lý do là TM có thể tạo mã tùy ý từ các mẫu, nhưng không thể sửa đổi mã không phải mẫu. Chuyển đổi chương trình có thể mô phỏng TM nếu bạn nhấn mạnh, và vì vậy ít nhất là mạnh mẽ, nhưng nó cũng có thể thực hiện các thay đổi tùy ý đối với mã mẫu không. Do đó, nghiêm chỉnh hơn.

Giống như TM, việc sử dụng các phép biến đổi chương trình cần phải nỗ lực để tìm hiểu và áp dụng. Nhưng việc có thể thao tác các chương trình theo các cách tùy ý có vẻ khá hữu ích.

(Chúng tôi đã thực hiện tái cấu trúc kiến ​​trúc các ứng dụng C++ rất lớn bằng DMS. TM không thể thực hiện việc này).

+0

Xem thêm http://stackoverflow.com/a/21358087/120163 –

0

Nếu C++ 0x là một tùy chọn, sau đó một số vấn đề lập trình meta mẫu có thể được giảm xuống thành tập hợp các hàm constexpr được thực thi tại thời gian biên dịch. Ví dụ: xem xét compile-time regex matcher using constexpr. các hàm constexpr cũng là faster so với các chương trình meta mẫu C++.

Nếu bạn tham gia lập trình chức năng, một số tùy chọn khác cũng có sẵn.

C++ Template Metaprogramming with Embedded Haskell

Meta Towards a Functional-Style Interface for C++ Template Metaprograms

Papers by Abel Sinkovics