ไม่มีคำเตือนเกี่ยวกับการแปลงโดยนัย

// g++ sizeofint.cpp --std=c++11 -Wconversion -Wall -Wextra -Werror -pedantic-errors
#include <iostream>
#include <utility>

int main(int argc, char **argv) {
    (void)argc;
    (void)argv;
    int a = 0x12345678;
    std::cout << sizeof(int) << "..." << sizeof(uint16_t) << std::endl;
    std::pair<uint16_t, uint16_t> p{a,a}; // !!!! no warning or error on conversion !!!!
    std::cout << p.first << ":" << p.second << std::endl;
    uint16_t b = a; // !!!! correct behavior: -Wconversion triggers warning, which -Werror turns to an error
    std::cout << b << std::endl;
    return 0;
}

ด้วยโค้ดด้านบน คุณจะเห็นการแปลงโดยนัยจาก int เป็น uint16_t ได้อย่างชัดเจนเมื่อสร้าง p อย่างไรก็ตาม g++ ในเวอร์ชัน 4.9.1 ไม่ได้บ่นเกี่ยวกับการแปลงใดๆ เมื่อใช้พารามิเตอร์ที่ให้ไว้ในความคิดเห็นในตอนต้น

ต่อมา g++ จะบ่นเกี่ยวกับการแปลงโดยนัยเป็น uint16_t เมื่อสร้าง b

ฉันกำลังพยายามให้แน่ใจว่าการก่อสร้างของ p จะส่งผลให้เกิดคำเตือนเป็นอย่างน้อย (แต่ควรมีข้อผิดพลาด)

มีความคิดอะไรบ้าง? มีการตั้งค่าสถานะที่ฉันไม่รู้ว่าจะกระตุ้นให้เกิดพฤติกรรมที่ถูกต้องหรือไม่


person inetknght    schedule 27.08.2014    source แหล่งที่มา
comment
คุณกดตัวสร้าง template<class U, class V> constexpr pair(U&& x, V&& y); ของ std::pair เนื่องจากการแปลงเกิดขึ้นจริงภายในตัวสร้างนั้น (ในส่วนหัวของระบบ) คุณจึงไม่ได้รับคำเตือน   -  person T.C.    schedule 27.08.2014
comment
ถ้าการก่อสร้างนั้นอยู่ภายในห้องสมุด ฉันก็คงเข้าใจได้ แต่อย่างที่คุณบอก นี่อยู่ในเทมเพลต... ซึ่งถูกคอมไพล์แล้ว ดังนั้น ควรตรวจสอบ   -  person inetknght    schedule 27.08.2014
comment
@ที.ซี. มันควรจะเป็นคำตอบใช่ไหม?   -  person Slava    schedule 27.08.2014
comment
เอกสาร gcc : คำเตือนทั้งหมด นอกเหนือจากที่สร้างโดย '#warning ' (ดูการวินิจฉัย) จะถูกระงับในขณะที่ GCC กำลังประมวลผลส่วนหัวของระบบ ดู ตัวอย่างที่คุณแก้ไขจะให้คำเตือนที่คาดหวัง   -  person quantdev    schedule 27.08.2014
comment
มีวิธีใดบ้างที่จะเปิดใช้งานคำเตือนสำหรับส่วนหัวของระบบ?   -  person inetknght    schedule 27.08.2014
comment
@Arkadiy น่าเสียดายที่ไม่ใช่   -  person inetknght    schedule 27.08.2014
comment
@millsj ขอบคุณที่ใช้งานได้ แน่นอนว่าตอนนี้ยังมีเรื่องไร้สาระอีกมากมาย... แค่เน้นย้ำว่าเวทมนตร์เบื้องหลังถูกแฮ็กเข้าด้วยกันมากแค่ไหน :(   -  person inetknght    schedule 27.08.2014


คำตอบ (1)


หากโค้ดของคุณใช้ตัวสร้าง constexpr pair(const uint16_t& x, const uint16_t& y); ของ std::pair<uint16_t, uint16_t> คุณจะได้รับคำเตือนและ/หรือข้อผิดพลาด คุณไม่จำเป็นต้องใช้ -Wconversion สำหรับสิ่งนี้ด้วยซ้ำ การแปลงที่แคบลงภายในเครื่องหมายปีกกาทำให้โปรแกรมมีรูปแบบไม่ถูกต้อง

แต่กลับเลือกความละเอียดโอเวอร์โหลดที่เลือกคอนสตรัคเตอร์ template<class U, class V> constexpr pair(U&& x, V&& y); ของ std::pair ซึ่งเหมาะสมกว่า เป็นผลให้การแปลงเกิดขึ้น ไม่ใช่ภายในโค้ดที่คุณเขียน แต่อยู่ภายในตัวสร้างนั้น เนื่องจากตัวสร้างนั้นถูกกำหนดไว้ในส่วนหัวของระบบ (ดูเอกสารประกอบของ GCC หมวก tip @quantdev) คำเตือนถูกระงับโดย GCC

แม้ว่าคุณสามารถใช้ -Wsystem-headers เพื่อเปิดใช้งานคำเตือนจากส่วนหัวของระบบ ตัวเลือกนั้นจะสร้างคำเตือนที่ไม่เกี่ยวข้องมากมาย และโต้ตอบกับ -Werror ได้แย่มาก

person T.C.    schedule 27.08.2014