Có phải các mẫu C ++ chỉ là một loại macro được tôn vinh?


27

Từ các so sánh khác nhau giữa các mẫu C ++ và chung chung C # / Java như thế này-

https://stackoverflow.com/questions/31693/what-are-the-differences-b between-generic-in-c-and-java-and-temsheet-in-c/31929 #31929

Tôi có một nhận thức rằng, các mẫu C ++ được triển khai bằng một số loại tiền xử lý (thay thế văn bản thuần túy trước khi phân tích cú pháp), không biên dịch. Bởi vì kiểu kiểm tra trong các mẫu C ++ giống với các macro C. Ý tôi là, nếu có một số lỗi, chúng là lỗi từ mã được tạo sau khi xử lý các khối mã templated, không phải từ chính các mẫu. Nói cách khác, chúng chỉ là một loại phiên bản macro của C.

Sau đó, tôi tìm thấy một số sự thật khác hỗ trợ này-

  • Tôi nghĩ, nếu các mẫu C ++ được thực hiện bằng tiền xử lý, sẽ có vấn đề với liên kết động (sử dụng. Và một googling nhanh chóng hỗ trợ này.

  • Một điểm khác là, hằng số nguyên có thể được truyền dưới dạng đối số cho các mẫu. Và nó thậm chí còn hỗ trợ một số loại đệ quy. Nhưng đệ quy này không được tìm thấy trong mã lắp ráp / mã máy đã biên dịch. Điều đệ quy được quản lý trong thời gian biên dịch bằng cách tạo một hàm cho mỗi cuộc gọi đệ quy và do đó có một nhị phân thực thi lớn hơn nhưng nhanh hơn.

Mặc dù không giống như macro C, nó có một số khả năng vượt trội. Nhưng không phải mẫu C ++ được triển khai với một số loại tiền xử lý? Làm thế nào điều này được thực hiện trong các trình biên dịch C ++ khác nhau?


19
Không. Các mẫu C ++ được biên dịch.
Edward Strange

2
Định nghĩa của bạn về "tiền xử lý" là gì? Và "biên dịch"? Một định nghĩa đủ rộng về "tiền xử lý" có thể bao gồm mọi thứ mà trình biên dịch thực hiện; Rốt cuộc, một trình biên dịch thực sự chỉ xử lý nguồn trước khi nó được thực thi, phải không?
James McNellis

@James McNellis IMHO nếu bạn chỉ có thể phân biệt tiền xử lý với tất cả những thứ khác được thực hiện để biên dịch, nó là đủ để hiểu câu hỏi của tôi. Để làm rõ tiền xử lý- en.wikipedia.org/wiki/Pre Processor
Lexical_pre Processors

6
Nếu bạn đang đề cập đến hình thức tiền xử lý đó, thì không, các mẫu C ++ hoàn toàn không chỉ là một loại macro được tôn vinh.
James McNellis

1
Ngôn ngữ mẫu thực sự đã hoàn tất, vì vậy chúng không chỉ là các macro nâng cao.
davidk01

Câu trả lời:


9

Các mẫu C ++ là một loại macro Lisp (hoặc thậm chí nhiều hơn, Scheme). Đây là ngôn ngữ hoàn chỉnh Turing đánh giá thời gian biên dịch, nhưng nó bị hạn chế nghiêm trọng vì không có quyền truy cập từ ngôn ngữ đó vào môi trường C ++ bên dưới. Vì vậy, vâng, các mẫu C ++ có thể được xem như một dạng tiền xử lý, với sự tương tác rất hạn chế với mã được tạo.


2
"nhưng nó bị hạn chế nghiêm trọng vì không có quyền truy cập từ ngôn ngữ đó vào môi trường C ++ bên dưới." -- Nó có nghĩa là gì? Tôi đã cố phân tích câu nói này, nhưng không thành công.
quant_dev

2
Uhm, thực sự ... github.com/kmichel/bf0x
Anton Golov

3
@ SK-logic: Ở một khía cạnh khác, C ++ 11 C ++, trừ khi bạn (về mặt giáo dục) đối xử với các phiên bản khác nhau của cùng một ngôn ngữ như các ngôn ngữ khác nhau.
Jon Purdy

3
@Jon Purdy, C ++ 11 không tồn tại (chính thức) tại thời điểm trả lời này. Ngày nay, một ví dụ sẽ phức tạp hơn, như phân tách cấu trúc dữ liệu, sử dụng chức năng thư viện, v.v.
SK-logic

1
@ SK-logic: Bạn có biết triển khai C ++ với các macro giống Lisp không? Tôi đang phát ốm vì những hạn chế của mẫu. Một ví dụ về ngôn ngữ cú pháp kiểu C ++ với hệ thống macro mạnh mẽ trong Haxe: haxe.org/manual/macros . (Không giúp tôi vì tôi sử dụng C ++ cho mục đích của nó - lập trình vi điều khiển 8 bit; có ngôn ngữ tốt hơn cho mọi thứ khác).
pfalcon

41

Có lẽ sự khác biệt lớn nhất là các macro C được mở rộng trong giai đoạn tiền xử lý, trước khi bất kỳ quá trình biên dịch nào khác được thực hiện, trong khi các mẫu C ++ là một phần của quá trình biên dịch. Điều này có nghĩa là các mẫu C ++ nhận biết kiểu và phạm vi, trong số những thứ khác, và không phải là sự thay thế văn bản đơn giản. Chúng có thể biên dịch thành các hàm thực, và do đó tránh được hầu hết các vấn đề mà macro gặp phải. Nhận biết kiểu có nghĩa là chúng có thể chung chung hoặc chuyên biệt: ví dụ, thật dễ dàng để cung cấp một swaphàm mẫu và dễ dàng viết các chuyên môn hoạt động tốt ngay cả khi các đối tượng quản lý bộ nhớ heap.

Do đó: Các mẫu C ++ không được tiền xử lý theo cùng một macro, chúng không phải là một loại macro C và không thể sử dụng các macro C để sao chép các mẫu làm gì.

Các mẫu sống trong các tệp tiêu đề, không phải trong các thư viện được liên kết, đúng, nhưng nếu bạn đang cung cấp một tệp ZIP thì có lẽ bạn cũng đang cung cấp một tệp tiêu đề để sử dụng.


12
Họ không cần phải sống trong tệp tiêu đề (đó chỉ là kỹ thuật đơn giản nhất để sử dụng chúng). Bạn có thể định nghĩa chúng trong tệp nguồn và bắt buộc khởi tạo mẫu trong tệp nguồn (đơn vị biên dịch) theo cách thủ công. Liên kết sau đó sẽ chọn các cảnh báo như bình thường (đây là một kỹ thuật giới hạn các mẫu cho các loại cụ thể và không cho phép tất cả các loại chung chung).
Martin York

@Martin: Tôi không chắc liệu kỹ thuật này (trong khi được hỗ trợ) có thực sự được hỗ trợ theo tiêu chuẩn hay không. Nếu không, tất cả các trình biên dịch đã exportthực hiện rồi. Tôi biết nó là loại công việc cho các chức năng, nhưng tôi nghi ngờ nó hoạt động cho các lớp: làm thế nào bạn biết kích thước của chúng?
Matthieu M.

@Matthieu M: Điều này không liên quan gì đến từ khóa xuất khẩu. Nó liên quan đến khởi tạo mẫu "Rõ ràng" và được xác định rõ trong tiêu chuẩn.
Martin York

2
@Matthieu M.: Nếu trình biên dịch biết chữ ký của hàm và trình liên kết có thể tìm thấy một triển khai, mọi thứ đều tuyệt. Điều đó áp dụng cho dù chức năng đó có phải là chức năng mẫu hay không. Trong thực tế, chúng thường sống trong các tệp tiêu đề, bởi vì việc ép buộc các thời điểm cụ thể thường hoạt động nhiều hơn giá trị của nó, nhưng Martin đã đúng khi lưu ý đến phương án thay thế.
David Thornley

Tôi biết nó hoạt động, chắc chắn, cho các chức năng chuyên ngành. Tuy nhiên tôi cũng khá chắc chắn rằng nó không hoạt động cho các lớp học, đó là quan điểm của tôi. Tôi nghĩ rằng nó cũng hoạt động cho các phương thức từ các lớp chuyên biệt, nhưng không biết liệu đây có phải là tiêu chuẩn hay không.
Matthieu M.

5

Có vấn đề như thế nào chúng được thực hiện? Các trình biên dịch C ++ ban đầu chỉ là các bộ xử lý trước đã cung cấp mã cho trình biên dịch ac, điều đó không có nghĩa là C ++ chỉ là một macro được tôn vinh.

Các mẫu loại bỏ sự cần thiết của một macro bằng cách cung cấp một cách an toàn hơn, hiệu quả hơn và đặc biệt hơn (thậm chí tôi không nghĩ đó là một từ thực sự) để triển khai mã cho nhiều loại.

Có nhiều cách khác nhau để thực hiện mã loại templating trong c, không có cách nào hay cả khi bạn vượt qua các kiểu đơn giản.


Tôi chưa nói về C ++ là một macro được tôn vinh. Tôi ngưỡng mộ C ++ rất nhiều. Chỉ tò mò thôi.
Gul Sơn

2
@Gulshan: Không, bạn đã không nói gì về điều đó. Tuy nhiên, đó là cách trình biên dịch C ++ hoạt động sớm (ngoại trừ CFront là thứ gì đó của trình biên dịch thay vì chỉ là bộ tiền xử lý macro) và các tuyên bố của bạn về các mẫu C ++ cũng có thể áp dụng cho chính C ++ ban đầu.
David Thornley

CFront đã biên dịch C ++ thành C. Dòng giữa bộ tiền xử lý và trình biên dịch được xác định rõ ràng: trình biên dịch cố gắng hiểu đầu vào của nó thông qua phân tích cú pháp, xây dựng AST, và trong khi một bộ tiền xử lý không ví dụ, chỉ sử dụng thay thế văn bản hoặc mã thông báo.
Jon Purdy

1
Tôi nghĩ điều David muốn nói là có một tập hợp con cơ bản của C ++ và các mẫu đó có thể được coi là một loại macro được sử dụng để nói chung một chương trình trong tập hợp con này, sau đó có thể được biên dịch thành một giai đoạn riêng biệt hơn nữa.
Giorgio

5

Có một số khác biệt; ví dụ, các mẫu có thể được sử dụng để khởi tạo quá tải hàm khi cần, trong khi với macro, bạn phải mở rộng macro một lần cho mỗi lần quá tải có thể để trình biên dịch hiển thị, vì vậy bạn sẽ kết thúc với rất nhiều mã không sử dụng.

Một sự khác biệt nữa là các mẫu tôn vinh không gian tên.


2

Các mẫu IMHO, C ++ và C Macros có nghĩa là để giải quyết hai vấn đề hoàn toàn khác nhau. Thư viện mẫu tiêu chuẩn C ++ ban đầu là một cơ chế để tách sạch các lớp container (mảng, danh sách liên kết, v.v.) khỏi các hàm chung thường được áp dụng cho chúng (như sắp xếp và ghép). Việc biểu diễn trừu tượng các thuật toán và cấu trúc dữ liệu hiệu quả dẫn đến mã biểu cảm hơn vì có ít phỏng đoán hơn trong cách thực hiện tốt nhất một hàm làm việc trên một phần dữ liệu cụ thể. Các macro C phù hợp hơn nhiều so với những gì người ta thường thấy trong các macro Lisp, ở chỗ chúng cung cấp một phương tiện để "mở rộng" ngôn ngữ với mã được in nghiêng. Điều thú vị là Thư viện chuẩn C ++ đã mở rộng chức năng của các mẫu để bao quát phần lớn những gì chúng ta sử dụng #define cho C.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.