ปัญหาคอมไพเลอร์ C ++ พร้อมโครงสร้างในคลาสเทมเพลต


13

รหัสต่อไปนี้ไม่ได้รวบรวมกับ gcc หรือเสียงดังกราว

template<class T>
class foo{};

template<class T>
class template_class_with_struct
{
    void my_method() {
        if(this->b.foo < 1);
    };

    struct bar
    {
        long foo;
    } b;
};

ข้อความแสดงข้อผิดพลาดคือ

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);

ข้อผิดพลาดเกิดจากคลาส templat foo เมื่อเขียน <= แทนที่จะเป็น <1 มันก็จะคอมไพล์ด้วย

คำใบ้ชื่นชมอะไรบ้าง?

ลิงก์ CompilerExplorer https://godbolt.org/z/v6Tygo


7
ผมจะบอกว่าข้อบกพร่องคอมไพเลอร์ แต่ msvc เป็นเพียงคนเดียวที่จะยอมรับมัน: - / สาธิต การทำงานที่เป็นไปได้รอบb.bar::fooหรือวงเล็บ ( (this->b.foo) < 1)
Jarod42

คำตอบ:


1

ใน GCC ฉันจะได้รับ

so.cpp:8:27: error: expected '>'
    if(this->b.foo < 1) 
                      ^

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

เมื่อคุณเปลี่ยนเป็น<=ซึ่งโทเค็นโดย lexer เป็นโทเค็นเดียว ขั้นตอนต่อไปไม่เห็นแม้แต่ a <ดังนั้นจึงไม่สับสน

หากคุณเปลี่ยนชั้นเรียนให้ไม่มีชื่อเหมือนกันกับระยะเวลานานแสดงbarว่าไม่มีปัญหานี้ นอกจากนี้ @ Jarod42 มีข้อเสนอแนะในความคิดเห็นของเขาสำหรับคำถามของคุณ (คุณสมบัติเพิ่มเติมหรือ parens)

คอมไพเลอร์ถูกเขียนเป็นขั้นตอนโดยที่แต่ละขั้นตอนแปลรหัสเป็นตัวแทนที่ดีขึ้นสำหรับขั้นตอนต่อไปและแต่ละขั้นตอนสามารถทำสิ่งที่ซับซ้อนมากขึ้นด้วยการเป็นตัวแทนนั้น

ในตอนเริ่มต้นคอมไพเลอร์ "lexes" โค้ดซึ่งเปลี่ยนอักขระแต่ละตัวในไฟล์ให้เป็นกระแสโทเค็น - มันจะเห็นบรรทัดนี้เป็นสิ่งที่ชอบ

// if(this->b.foo < 1) 
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)

fooและจากนั้นก็จะได้รับไป มันน่าจะทำ

- name(foo)
- operator(<)
- number(1)
- right-paren

แต่ดูเหมือนว่าฉันจะเห็นเมื่อมันมองfooไปข้างหน้าเห็น<และความจริงที่foo<class T>มีอยู่และมันพยายามที่จะทำโทเค็นเดียวจากfoo< ...แต่ก็ไม่สามารถหา>ให้เสร็จสมบูรณ์ได้

นี่เป็นเพียงการคาดเดา - อาจเป็นขั้นตอนที่ผ่านมากับ lexer ที่พยายามค้นหาชื่อและสามารถรวมโทเค็นได้ ไม่ว่าในกรณีใดการใช้งานหลายอย่างของ foo จะหลอกมัน


ฉันเข้าใจคำอธิบายของคุณ แต่ไม่แน่ใจว่านั่นแปลว่าคอมไพเลอร์ควรประพฤติตัวอย่างไร บางทีนี่อาจเป็นฟิลด์ที่เป็นข้อบกพร่องสำหรับคอมไพเลอร์ที่แตกต่างกัน บางครั้งคุณอาจไม่ทราบว่าเทมเพลตคลาสใดที่อยู่ในส่วนหัวของไลบรารีที่เชื่อมโยง (ชื่อสามัญเช่น cnt, count, counter ... )
eactor

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