ฉันคิดว่าคำตอบทั้งหมดได้กล่าวถึงtypename
คำหลักนั้นใช้ในสองกรณีที่แตกต่างกัน:
a) เมื่อประกาศพารามิเตอร์ประเภทเทมเพลต เช่น
template<class T> class MyClass{}; // these two cases are
template<typename T> class MyNewClass{}; // exactly the same.
ซึ่งไม่มีความแตกต่างระหว่างพวกเขาและพวกเขาเหมือนกันอย่างแน่นอน
b) ก่อนที่จะใช้ชื่อประเภทที่ขึ้นกับซ้อนกันสำหรับเทมเพลต
template<class T>
void foo(const T & param)
{
typename T::NestedType * value; // we should use typename here
}
ซึ่งการไม่ใช้typename
โอกาสในการขายทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ / คอมไพล์
สิ่งที่ฉันต้องการที่จะเพิ่มในกรณีที่สองเป็นที่กล่าวถึงในหนังสือสกอตเมเยอร์ที่มีประสิทธิภาพ C ++ , คือว่ามีข้อยกเว้นของการใช้typename
มาก่อนชื่อประเภทที่ซ้อนกันขึ้นอยู่กับ ข้อยกเว้นคือถ้าคุณใช้ชื่อชนิดอ้างอิงที่ซ้อนกันเป็น aคลาสฐานหรือในรายการการเริ่มต้นสมาชิกคุณไม่ควรใช้ที่typename
นั่น:
template<class T>
class D : public B<T>::NestedType // No need for typename here
{
public:
D(std::string str) : B<T>::NestedType(str) // No need for typename here
{
typename B<T>::AnotherNestedType * x; // typename is needed here
}
}
หมายเหตุ:การใช้typename
ไม่จำเป็นต้องสำหรับกรณีที่สอง (เช่นก่อนชื่อชนิดที่ขึ้นกับซ้อนกัน) เนื่องจาก C ++ 20