วิธีหลีกเลี่ยงการแปลงโดยนัยจากจำนวนเต็ม 0 ถึงตัวชี้เป็นองค์ประกอบของเวกเตอร์


11

มีสถานการณ์ที่ฉันต้องการรวบรวมชื่อโหนดทั้งหมดของพา ธ ไปยังคีย์ใน JSON พิจารณาเงื่อนไขของดัชนีอาเรย์ "0", "1" ด้วยเช่นกัน แต่มันก็ง่ายที่จะลืมเครื่องหมายคำพูดซึ่งจะนำไปสู่ความผิดพลาดเมื่อทำการอ้างอิง ดังนั้นฉันต้องการปฏิเสธสิ่งนี้ ตัวอย่าง:

#include <vector>
#include <iostream>

int func(const std::vector<const char*>& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

ฉันพบและลองสิ่งนี้ฉันจะหลีกเลี่ยงการแปลงโดยนัยในฟังก์ชั่นที่ไม่ได้สร้างได้อย่างไร ดังต่อไปนี้:

#include <vector>
#include <iostream>

int func(const std::vector<const char*>& pin) {
    return pin.size();
}

template<typename T>
int func(T pin) = delete;

int main() {
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

แต่คอมไพเลอร์ก็ยังไม่เข้าใจฉัน

ข้อเสนอแนะใด ๆ
โปรดชี้ให้เห็นถึงการใช้คำศัพท์และสมมุติฐานผิด ๆ ขอบคุณ!


มีเหตุผลทำไมคุณใช้std::vector<const char*>แทนstd::vector<std::string>>?
bolov

คุณต้องการห้ามnullptrหรือไม่
Jarod42

@bolov ที่จุดเริ่มต้นฉันพิจารณาที่จะส่งชื่อโหนดเหล่านี้ไปยังอินเตอร์เฟสการวิเคราะห์ JSON ซึ่งใช้อักขระ C * เป็นอินพุต แต่นี่ไม่ได้ จำกัด ที่นี่ ฉันได้ทดสอบแล้วโดยใช้ std :: vector <std :: string >> ยังคงยอมรับ 0 เมื่อคอมไพล์ แต่ล้มเหลวเมื่อทำงานบนเครื่องของฉัน GCC รายงานว่า "basic_string :: _ M_construct null ไม่ถูกต้อง"
rustyhu

@ Jarod42 ใช่สิ่งที่ต้องการคือสตริงตัวอักษร C
rustyhu

คำตอบ:


10

อะไรแบบนี้? มันคล้ายกับโซลูชันโอเวอร์โหลดที่คุณแนะนำ แต่จำเป็นต้องห่อด้วยเวกเตอร์ประเภท ไม่สามารถสร้างได้หากคุณระบุตัวอักษร0เนื่องจากเกินพิกัดตัวสร้างที่ถูกลบ

#include <memory>
#include <new>
#include <vector>
#include <iostream>
using std::vector;

template<typename T>
struct no_zero {
        no_zero(T val) : val(val) {}
        no_zero(int val) = delete;
        operator T() { return val; }
        T val;
};

int func(const vector<no_zero<const char*> >& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

4

ในตอนหลังการแปลงหลายอย่างโดยนัยใน C ++ นั้นโชคไม่ดีนี่เป็นหนึ่งในนั้น

ทางเลือกหนึ่งที่ควรพิจารณาคือ-Wzero-as-null-pointer-constantใน gcc และ clang โปรดใช้ความระมัดระวังเนื่องจากการเปลี่ยนแปลงลักษณะการทำงานของโปรแกรมมาตรฐานและหากเปิดใช้งานทั่วโลกอาจมีผลกระทบที่ไม่ตั้งใจ

g ++ - ฉันจะปิดการใช้งานการแปลงโดยนัยจาก 0 เป็นประเภทตัวชี้ได้อย่างไร

คำเตือนเสียงดังกังวานใดที่เทียบเท่ากับ Wzero-as-null-pointer-constant จาก GCC


3

ผมชอบคำตอบของมิเกล Rychliski อย่างไรก็ตามยังมีวิธีแก้ไขปัญหาในGuideline Support Library :

gsl::not_null

ฉันขอแนะนำ GSL มันถูกสร้างขึ้นและได้รับการสนับสนุนโดยผู้เชี่ยวชาญ C ++ มากมาย Bjarne Stroustrup ตัวเองและ Herb Sutter ในหมู่พวกเขา และC ++ Core Guidelinesนั้นถูกรวมเข้ากับคำเตือนของคอมไพเลอร์และเครื่องมือวิเคราะห์สแตติก

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