ปัญหาใน GCC / C ++ 17 พร้อมคลาสเทมเพลตเทมเพลต


10

พิจารณาโอเวอร์โหลด 2 ตัวต่อไปนี้

template<typename T>
bool test() {
    return true;
}

template<template<typename ...> class T>
bool test() {
    return false;
}

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

    std::cout<<test<int>()<<std::endl; <-- this yields 1
    std::cout<<test<std::list>()<<std::endl; <--this yields 0

ตอนนี้ให้พิจารณาฟังก์ชั่นเทมเพลตต่อไปนี้:

template<typename U>
bool templfun(){
    struct A{
        bool f(){
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>();  // <-- this is ok
}

ใน GCC จะให้ข้อผิดพลาดสำหรับการแก้ปัญหาการโอเวอร์โหลดที่คลุมเครือในขณะที่ Clang คอมไพล์ น่าสนใจการเรียกเพื่อทดสอบครั้งที่สอง () ไม่ก่อให้เกิดข้อผิดพลาด (แม้แต่ใน GCC) นอกจากนี้หากฉันลบtemplate<typename U>สิ่งที่อยู่ด้านบนของ templfun, gcc หยุดบ่น

นี่เป็นข้อบกพร่องของ GCC หรือเป็นรหัสที่ผิดกฎหมายหรือไม่?

คำตอบ:


4

GCC ผิด struct Aเป็นนิติบุคคลที่ templatedแต่ไม่ชัดเจนแม่แบบ (เพราะมันไม่ได้เริ่มต้นด้วยtemplateคำหลัก) จึงไม่มีความกำกวม

เพื่อยืนยันเราสามารถเปลี่ยนชื่อพารามิเตอร์ type เพื่อดูว่า G ++ พยายามใช้เทมเพลตเทมเพลตเกินพิกัด

template <typename X>
bool test() {
    return true;
}

template <template <typename...> class Y>
bool test() {
    return false;
}

template <typename U>
bool templfun() {
    struct A {
        bool f() {
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>(); // <-- this is ok
}

bool run() {
    return templfun<int>();
}

เอาต์พุต G ++: ( ลิงก์ไปยัง godbolt )

<source>:15:27: error: call of overloaded 'test<templfun() [with U = int]::A>()' is ambiguous
   15 |             return test<A>(); // <-- this gives an error
      |                    ~~~~~~~^~

<source>:2:6: note: candidate: 'bool test() [with X = templfun() [with U = int]::A]'
    2 | bool test() {
      |      ^~~~

<source>:7:6: note: candidate: 'bool test() [with Y = templfun()::A]'
    7 | bool test() {
      |      ^~~~

เห็นได้ชัดว่า " candidate: 'bool test() [with Y = templfun()::A]'" เป็นของปลอม

โปรดทราบว่าไม่อนุญาตประเภทท้องถิ่นเป็นอาร์กิวเมนต์แม่แบบก่อนหน้า C ++ 11 (ดู C ++ 03 § 14.3.1.2) เพื่อให้สามารถอธิบายความซับซ้อนของการนำ G ++ ไปใช้

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