เทมเพลต C ++ เป็นเพียงแมโครชนิดหนึ่งที่ได้รับการยกย่องหรือไม่?


27

จากการเปรียบเทียบที่แตกต่างกันระหว่างเทมเพลต C ++ และเจเนอรัล C # / Java เช่นนี้ -

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

ฉันเข้าใจว่ามีการใช้เทมเพลต C ++ โดยการประมวลผลล่วงหน้าบางอย่าง (การแทนที่ข้อความธรรมดาก่อนการแยกวิเคราะห์) ไม่ได้รวบรวม เนื่องจากการตรวจสอบชนิดในเทมเพลต C ++ มีลักษณะคล้ายกับมาโคร C ฉันหมายความว่าหากมีข้อผิดพลาดบางอย่างพวกเขาเป็นข้อผิดพลาดจากรหัสที่สร้างขึ้นหลังจากการประมวลผลบล็อกรหัส templated ไม่ใช่จากแม่แบบเอง กล่าวอีกนัยหนึ่งมันเป็นแค่มาโครระดับสูงในซี

จากนั้นฉันก็พบข้อเท็จจริงอื่น ๆ ที่สนับสนุนสิ่งนี้ -

  • ฉันคิดว่าถ้ามีการใช้เทมเพลต C ++ โดยการประมวลผลล่วงหน้าจะมีปัญหากับการเชื่อมโยงแบบไดนามิก (โดยใช้. dll) และ googling ที่รวดเร็วสนับสนุนสิ่งนี้

  • อีกจุดคือค่าคงที่จำนวนเต็มสามารถส่งผ่านเป็นอาร์กิวเมนต์ไปยังเทมเพลต และมันยังรองรับการเรียกซ้ำบางประเภท แต่การเรียกซ้ำนี้ไม่พบในรหัสแอสเซมบลีที่รวบรวม / เครื่อง สิ่งที่เรียกซ้ำได้รับการจัดการในเวลารวบรวมโดยการสร้างฟังก์ชั่นสำหรับทุกการโทรซ้ำและจึงมีไบนารีที่ปฏิบัติการขนาดใหญ่ แต่เร็วกว่า

แม้ว่าจะแตกต่างจากแมโคร C แต่มีความสามารถที่เหนือกว่า แต่เท็มเพลต C ++ ไม่ได้ถูกนำไปใช้กับการประมวลผลล่วงหน้าบางประเภทใช่หรือไม่ สิ่งนี้นำไปใช้ในคอมไพเลอร์ C ++ ที่แตกต่างกันอย่างไร


19
Nope เท็มเพลต C ++ ถูกคอมไพล์
Edward Strange

2
คำจำกัดความของคุณของ "การประมวลผลล่วงหน้า" คืออะไร? และจาก "การรวบรวม"? คำจำกัดความที่กว้างเพียงพอของ "การประมวลผลล่วงหน้า" อาจรวมทุกอย่างที่คอมไพเลอร์ทำ ท้ายที่สุดคอมไพเลอร์ก็ประมวลผลแหล่งข้อมูลก่อนที่จะถูกประมวลผลจริง ๆ ใช่ไหม?
James McNellis

@James McNellis IMHO หากคุณสามารถแยกความแตกต่างของการประมวลผลล่วงหน้าจากสิ่งอื่น ๆ ทั้งหมดที่ทำเพื่อการรวบรวมมันก็เพียงพอที่จะเข้าใจคำถามของฉัน สำหรับการทำความเข้าใจพรีโปรเซสเซอร์
Gulshan

6
หากคุณอ้างถึงรูปแบบของการประมวลผลล่วงหน้าดังนั้นไม่เทมเพลต C ++ นั้นไม่ใช่เพียงแค่มาโครที่ได้รับการยกย่อง
James McNellis

1
ภาษาเทมเพลตนั้นได้รับการทำให้สมบูรณ์จริง ๆ ดังนั้นจึงเป็นมากกว่าแมโครที่ได้รับการปรับปรุง
davidk01

คำตอบ:


9

เทมเพลต C ++ นั้นเป็นมาโครแบบ Lisp ที่ช้าลง (หรือมากกว่านั้น) มันเป็นภาษาทัวริงที่สมบูรณ์ซึ่งประเมินในเวลารวบรวม แต่มัน จำกัด อย่างรุนแรงเนื่องจากไม่มีการเข้าถึงจากภาษานั้นไปยังสภาพแวดล้อม C ++ ดังนั้นใช่เทมเพลต C ++ สามารถมองเห็นเป็นรูปแบบของการประมวลผลล่วงหน้าบางรูปแบบโดยมีการโต้ตอบที่ จำกัด มากกับรหัสที่สร้างขึ้น


2
"แต่มีข้อ จำกัด อย่างรุนแรงเนื่องจากไม่มีการเข้าถึงจากภาษาดังกล่าวไปยังสภาพแวดล้อม C ++" - มันหมายความว่าอะไร? ฉันพยายามแยกคำสั่งนี้ แต่ล้มเหลว
quant_dev

2
อืมจริงๆแล้ว ... github.com/kmichel/bf0x
Anton Golov

3
@ SK-logic: ในขณะเดียวกัน C ++ 11 คือ C ++ ยกเว้นว่าคุณ (อวดรู้) จะปฏิบัติต่อภาษาเดียวกันกับภาษาที่แตกต่างกัน
Jon Purdy

3
@Jon Purdy, C ++ 11 ไม่มีอยู่ (เป็นทางการ) ตามเวลาของคำตอบนี้ ทุกวันนี้ตัวอย่างจะมีความซับซ้อนมากขึ้นเช่นการสลายโครงสร้างข้อมูลโดยใช้ฟังก์ชั่นห้องสมุด ฯลฯ
SK-logic

1
@ SK-logic: คุณรู้จักการใช้ C ++ กับมาโครที่มีรูปร่างเหมือนกระเพื่อมหรือไม่? ฉันเบื่อข้อ จำกัด ของแม่แบบ ตัวอย่างของภาษา C ++ - ภาษาไวยากรณ์สไตล์ด้วยระบบมาโครที่มีประสิทธิภาพใน Haxe: haxe.org/manual/macros (ไม่ช่วยฉันเพราะฉันใช้ C ++ เพื่อจุดประสงค์ - การเขียนโปรแกรมไมโครคอนโทรลเลอร์ 8 บิต; มีภาษาที่ดีกว่าสำหรับสิ่งอื่น)
pfalcon

41

ความแตกต่างที่ใหญ่ที่สุดอาจเป็นได้ว่ามาโคร C จะถูกขยายในระยะการประมวลผลก่อนก่อนที่จะทำการรวบรวมอื่น ๆ ในขณะที่แม่แบบ C ++ นั้นเป็นส่วนหนึ่งของการรวบรวม ซึ่งหมายความว่าเทมเพลต C ++ นั้นรับรู้ชนิดและกำหนดขอบเขตเหนือสิ่งอื่นใดและไม่ใช่การแทนที่ข้อความแบบง่าย พวกเขาสามารถคอมไพล์ไปยังฟังก์ชั่นจริงและหลีกเลี่ยงมาโครปัญหาส่วนใหญ่ได้ การตระหนักถึงประเภทนั้นหมายความว่าพวกมันสามารถเป็นแบบทั่วไปหรือแบบพิเศษได้ตัวอย่างเช่นมันง่ายที่จะให้swapฟังก์ชั่นเทมเพลตและง่ายต่อการเขียนความเชี่ยวชาญที่ทำงานได้ดีแม้ว่าวัตถุจะจัดการหน่วยความจำฮีป

ดังนั้น: เท็มเพลต C ++ ไม่ได้ทำการประมวลผลล่วงหน้าในมาโครที่มีความหมายเหมือนกันพวกมันไม่ใช่มาโครแบบ C และเป็นไปไม่ได้ที่จะใช้มาโคร C เพื่อทำซ้ำสิ่งที่เทมเพลตทำ

เทมเพลตอาศัยอยู่ในไฟล์ส่วนหัวไม่ใช่ในไลบรารีที่เชื่อมโยงจริง แต่ถ้าคุณจัดหา. dll คุณก็น่าจะเป็นผู้จัดหาไฟล์ส่วนหัวเพื่อให้ใช้


12
พวกเขาไม่จำเป็นต้องอยู่ในไฟล์ส่วนหัว (นั่นเป็นเทคนิคที่ง่ายที่สุดในการใช้งาน) คุณสามารถกำหนดได้ในไฟล์ต้นฉบับและบังคับให้สร้างอินสแตนซ์ของเทมเพลตในไฟล์ต้นฉบับ (หน่วยการรวบรวม) ด้วยตนเอง การเชื่อมโยงจะรับอินสแตนซ์ตามปกติ (นี่เป็นเทคนิคในการ จำกัด แม่แบบเฉพาะบางประเภทและไม่อนุญาตประเภททั่วไปทั้งหมด)
Martin York

@ มาร์ติน: ฉันไม่แน่ใจว่าเทคนิคนี้ (ได้รับการสนับสนุนในขณะนี้) ได้รับการสนับสนุนอย่างชัดเจนโดยมาตรฐาน มิฉะนั้นคอมไพเลอร์ทั้งหมดจะได้exportนำไปใช้งานแล้ว ฉันรู้ว่ามันใช้งานได้กับฟังก์ชั่นต่าง ๆ แต่ฉันสงสัยว่ามันใช้ได้กับคลาส: คุณจะรู้ขนาดของมันได้อย่างไร
Matthieu M.

@Matthieu M: นี่ไม่เกี่ยวกับคำหลักส่งออก มันเกี่ยวข้องกับการเริ่มต้นแม่แบบ "ชัดเจน" และมีการกำหนดไว้เป็นอย่างดีในมาตรฐาน
Martin York

2
@Matthieu M .: หากคอมไพเลอร์รู้ถึงลายเซ็นของฟังก์ชั่นและ linker สามารถค้นหาการนำไปใช้งานได้ทุกอย่างก็เจ๋ง ที่ใช้ไม่ว่าฟังก์ชันนั้นจะเป็นฟังก์ชันแม่แบบหรือไม่ ในทางปฏิบัติพวกมันมักอาศัยอยู่ในไฟล์ส่วนหัวเนื่องจากการบังคับให้อินสแตนซ์เฉพาะนั้นใช้งานได้มากกว่าที่ควรค่า แต่มาร์ตินนั้นถูกต้องในการสังเกตทางเลือก
David Thornley

ฉันรู้ว่ามันใช้งานได้แน่นอนสำหรับฟังก์ชั่นพิเศษ อย่างไรก็ตามฉันก็ค่อนข้างแน่ใจว่ามันไม่ทำงานสำหรับชั้นเรียนซึ่งเป็นจุดของฉัน ฉันคิดว่ามันใช้ได้กับวิธีการจากคลาสเฉพาะด้วย แต่ไม่ทราบว่านี่เป็นมาตรฐานหรือไม่
Matthieu M.

5

มันมีความสำคัญอย่างไรกับการปรับใช้ คอมไพเลอร์ C ++ รุ่นแรกเป็นเพียงตัวประมวลผลล่วงหน้าที่ป้อนรหัสไปยังคอมไพเลอร์ ac มันไม่ได้หมายความว่า C ++ เป็นเพียงแมโครที่ได้รับเกียรติ

เทมเพลตช่วยลดความจำเป็นในการใช้งานแมโครด้วยการนำเสนอวิธีที่ปลอดภัยกว่ามีประสิทธิภาพและพิเศษกว่า (แม้ว่าฉันจะไม่คิดว่าเป็นคำจริง) ในการติดตั้งโค้ดสำหรับหลาย ๆ ประเภท

มีหลากหลายวิธีในการพิมพ์รหัสเทมเพลตใน c ซึ่งไม่มีวิธีไหนที่ดีมากเมื่อคุณได้รับมากกว่าประเภทที่เรียบง่าย


ฉันไม่ได้พูดเกี่ยวกับ C ++ ว่าเป็นมาโครที่ได้รับเกียรติ ฉันชื่นชม C ++ มาก ๆ แค่อยากรู้อยากเห็น
Gulshan

2
@Gulshan: ไม่คุณไม่ได้พูดอะไรเกี่ยวกับเรื่องนั้น อย่างไรก็ตามนั่นเป็นสิ่งที่คอมไพเลอร์ C ++ ทำงานเร็ว (ยกเว้นว่า CFront เป็นคอมไพเลอร์แทนที่จะเป็นเพียงตัวประมวลผลล่วงหน้าของแมโคร) และคำสั่งของคุณเกี่ยวกับเทมเพลต C ++ นั้นใช้ได้กับ C ++ ตัวแรก
David Thornley

CFront ที่คอมไพล์ C ++ ถึง C บรรทัดระหว่างตัวประมวลผลล่วงหน้าและคอมไพเลอร์ถูกกำหนดไว้อย่างชัดเจน: คอมไพเลอร์พยายามที่จะเข้าใจอินพุตของมัน - ผ่านการแยกวิเคราะห์, การสร้าง AST, & c.- ในขณะที่ตัวประมวลผลล่วงหน้าไม่ใช้เช่นการทดแทนเฉพาะข้อความหรือโทเค็นเท่านั้น
Jon Purdy

1
ฉันคิดว่าสิ่งที่เดวิดหมายถึงคือมีเซตย่อยของ C ++ และแม่แบบนั้นสามารถคิดได้ว่าเป็นมาโครบางชนิดที่ใช้สำหรับโปรแกรมทั่วไปในชุดย่อยนี้ซึ่งสามารถรวบรวมเป็นอีกขั้นตอนแยกต่างหาก
Giorgio

5

มีความแตกต่างบางอย่าง; ตัวอย่างเช่นเทมเพลตสามารถใช้เพื่อยกตัวอย่างฟังก์ชั่นการโอเวอร์โหลดเมื่อจำเป็นในขณะที่มาโครคุณจะต้องขยายมาโครหนึ่งครั้งสำหรับการโอเวอร์โหลดแต่ละครั้งที่เป็นไปได้เพื่อที่จะให้มันปรากฏแก่คอมไพเลอร์ ของรหัสที่ไม่ได้ใช้

ความแตกต่างก็คือแม่แบบให้เกียรติเนมสเปซ


2

IMHO เทมเพลต C ++ และมาโคร C มีไว้เพื่อแก้ไขปัญหาที่แตกต่างกันสองอย่าง เทมเพลตไลบรารี C ++ มาตรฐานดั้งเดิมเป็นกลไกในการแยกคลาสคลาสคอนเทนเนอร์ (อาร์เรย์รายการที่ลิงก์และอื่น ๆ ) ออกจากฟังก์ชั่นทั่วไปที่ใช้กับพวกมัน (เช่นการเรียงลำดับและการเรียงต่อกัน) การมีการนำเสนอนามธรรมของอัลกอริธึมที่มีประสิทธิภาพและโครงสร้างข้อมูลนำไปสู่โค้ดที่แสดงออกมากขึ้นเนื่องจากมีการคาดเดาน้อยลงในวิธีที่ดีที่สุดในการใช้ฟังก์ชันที่ทำงานกับข้อมูลบางส่วน มาโคร C มีความสอดคล้องกับสิ่งที่คนทั่วไปมักจะเห็นในมาโคร Lisp ซึ่งพวกเขาได้จัดเตรียมวิธีการ "ขยาย" ภาษาด้วยโค้ดอินไลน์ สิ่งที่น่าสนใจคือ C ++ Standard Library ได้ขยายฟังก์ชันการทำงานของเทมเพลตเพื่อให้ครอบคลุมส่วนใหญ่ที่เราใช้ #define ใน C

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.