ฉันจะสร้างอินสแตนซ์ฟังก์ชันเทมเพลตอย่างชัดเจนได้อย่างไร


117

ฉันมีฟังก์ชันเทมเพลตที่มีอาร์กิวเมนต์เดียว ฉันต้องสร้างอินสแตนซ์ของฟังก์ชันนั้นโดยไม่เรียกใช้ฟังก์ชันนั้นหมายความว่าฉันต้องสร้างอินสแตนซ์อย่างชัดเจน

ฉันมีฟังก์ชั่นนี้:

template <class T> int function_name(T a) {}

ฉันสร้างอินสแตนซ์ฟังก์ชันนั้นดังนี้:

template int function_name<int>(int);

แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

error: expected primary-expression before 'template'
error: expected `;' before 'template'

คำตอบ:


182

[แก้ไข 2]: โปรดทราบว่ามีความสับสนเกี่ยวกับโค้ดในคำถามเดิมเนื่องจากปัญหาการจัดรูปแบบโค้ด ดูคำตอบของ AnthonyHatchkins สำหรับรายละเอียดเพิ่มเติม

หากคุณต้องการสร้างอินสแตนซ์ (แทนที่จะเชี่ยวชาญหรือบางสิ่งบางอย่าง) ให้ทำสิ่งนี้:

template <typename T> void func(T param) {} // definition

template void func<int>(int param); // explicit instantiation.

[แก้ไข] ดูเหมือนจะมีความสับสน (มาก) เกี่ยวกับการสร้างอินสแตนซ์และความเชี่ยวชาญที่ชัดเจน รหัสผมโพสต์ดังกล่าวข้างต้นข้อตกลงกับinstantiation อย่างชัดเจน ไวยากรณ์สำหรับความเชี่ยวชาญแตกต่างกัน นี่คือไวยากรณ์สำหรับความเชี่ยวชาญ:

template <typename T> void func(T param) {} // definition

template <> void func<int>(int param) {} // specialization

สังเกตว่าวงเล็บเหลี่ยมหลังแม่แบบ!


3
นั่นคือการสร้างอินสแตนซ์หรือความเชี่ยวชาญ ?
Nawaz

5
ไม่จริง. คุณสามารถบอกคอมไพลเลอร์ให้สร้างอินสแตนซ์เทมเพลตอย่างชัดเจน Google สำหรับ "C ++ Explicit template instantiation" สำหรับรายละเอียดเพิ่มเติม
ชม

8
@Nawaz: คุณคิดผิด แน่นอนว่าคอมไพเลอร์เป็นตัวที่สร้างอินสแตนซ์เสมอบรรทัดนั้นเป็นคำขอจากโปรแกรมเมอร์ไปยังคอมไพเลอร์เพื่อสร้างอินสแตนซ์เทมเพลต หากคุณมีสำเนาของมาตรฐาน C ++ โปรดอ่าน14.7.2 การสร้างอินสแตนซ์ที่ชัดเจน
David Rodríguez - dribeas

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

3
@hrnt: ฉันคิดว่าคุณพูดถูก @Ashot: ฉันเพิ่งสังเกตว่าไวยากรณ์ไม่มีtemplate<>รูปแบบ สิ่งที่เขาได้เขียนแตกต่างจากความเชี่ยวชาญ +1 เพื่อสอนสิ่งใหม่นี้ให้ฉัน ฉันกำลังลบโพสต์ของฉัน : D
Nawaz

20

รหัสของคุณถูกต้อง

ข้อความแสดงข้อผิดพลาดเกี่ยวข้องกับตำแหน่งในรหัสที่คุณไม่ได้อ้างถึงที่นี่

ปรับปรุง:

รหัสเดิมคือ

template <class T> int function_name(T a) {}
template int function_name<int>(int);

และถูกต้อง

แต่มันก็ไม่ได้ยกมาและทำให้การมองเช่นนี้

template int function_name(T a) {}
template int function_name(int);

มันสร้างข้อผิดพลาดต่อไปนี้

a.cpp:1: error: explicit instantiation of non-template int function_name
a.cpp:1: error: expected `;' before ‘(’ token
a.cpp:3: error: function_name is not a template function

ซึ่งแตกต่างจากที่ OP อ้างถึงอย่างชัดเจน

ในตัวแปรนี้บรรทัดที่สองใช้ได้ ( <int>สามารถข้ามได้ที่นี่) แต่บรรทัดแรกผิดพลาด คอมไพลเลอร์ไม่สามารถเดาได้ว่าTเป็นพารามิเตอร์เทมเพลต


ในทางเทคนิคมันไม่ใช่รหัสของเขา แต่เป็นการแก้ไขของบิล :) รหัสเดิมคือtemplate int function_name( T a) { }และtemplate int function_name(int);
ชม

@hrnt รหัสต้นฉบับไม่ได้อยู่ในรูปแบบที่ถูกต้อง แต่มันก็ถูกต้อง ถ้าฉันเป็นBalajiฉันจะกลับมาและยอมรับคำตอบของคุณถ้าเขาเห็นว่ามันมีประโยชน์ แต่สำหรับฉัน (และสันนิษฐานว่าสำหรับคนอื่น) คำตอบของคุณ (ในขณะที่เป็นได้อย่างสมบูรณ์แบบที่เหมาะสมด้วยตัวเอง) ไม่ได้ตอบคำถาม
Antony Hatchkins

@hrnt คุณคิดถูกแล้วที่รหัสเดิมเป็นแบบนั้น แต่เนื่องจากอาร์กิวเมนต์แม่แบบอนุมานจึงยังใช้งานได้ ฉันต้องเห็นด้วยกับ Antony Hatchkins ว่าข้อผิดพลาดเกิดจากโค้ดที่ OP ไม่ได้อ้างถึงอย่างไรก็ตามฉันคิดว่าคำตอบของคุณยังคงมีประโยชน์สำหรับผู้ที่ไม่ทราบเกี่ยวกับการสร้างอินสแตนซ์อย่างชัดเจน
mpark

เอาตัวอย่างฉัน ฉันใช้หน้านี้เมื่อต้องการรีเฟรชความรู้ที่ลืมไปดีเกี่ยวกับการสร้างอินสแตนซ์ที่ชัดเจน - และมันไม่ได้ช่วยอะไรฉันมากนัก สำหรับฉันไม่มีความสับสนเกี่ยวกับไวยากรณ์ สิ่งที่อาจทำให้เกิดความสับสนเกี่ยวกับการสร้างอินสแตนซ์ที่ชัดเจนคือการใช้งาน
Antony Hatchkins

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