ทำไมไม่มี std :: stou?


96

C ++ 11 เพิ่มฟังก์ชันการแปลงสตริงใหม่:

http://en.cppreference.com/w/cpp/string/basic_string/stoul

ซึ่งรวมถึง stoi (string to int), stol (string to long), stoll (string to long long), stoul (string to unsigned long), stoull (string to unsigned long long) สิ่งที่โดดเด่นในกรณีที่ไม่มีคือฟังก์ชัน stou (string to unsigned) มีเหตุผลบางอย่างที่ไม่จำเป็น แต่เหตุผลอื่น ๆ ทั้งหมดคืออะไร?

เกี่ยวข้อง: ไม่มีฟังก์ชัน "sto {short, unsigned short}" ใน C ++ 11?


6
คำถามของฉันมีจุดมุ่งหมายเพื่อให้สอดคล้องกับแนวความคิดของ "มีข้อเสียเปรียบที่ไม่ชัดเจนในการใช้ stoul" หรือไม่ เห็นได้ชัดว่ามันจะยุ่งกับการสร้างอินสแตนซ์เทมเพลต แต่มีอะไรอีกบ้างที่ฉันไม่ได้พิจารณา? ความคิดเห็นว่าทำไมถึงถูกปล่อยทิ้งไว้จะดี แต่เป็นเรื่องรอง
David Stone

13
@NicolBolas ฉันไม่เห็นว่าทำไมสิ่งนี้ถึงไม่สร้างสรรค์ เป็นคำถามที่ถูกต้องอย่างสมบูรณ์เนื่องจากฉันไม่สามารถมองเห็นเหตุผลใด ๆ สำหรับความไม่สอดคล้องกันนี้และ anwers อาจให้ข้อมูลเชิงลึกเกี่ยวกับเหตุผลที่ถูกต้องที่มีอยู่ แต่ไม่ใช่เหตุผลที่ชัดเจน
Christian Rau

4
@SethCarnegie ดีสิ่งที่แพลตฟอร์มของคุณ (และอาจจะส่วนใหญ่ของแพลตฟอร์ม) ไม่เป็นที่ไม่เกี่ยวข้องเพียงเพราะเพียงแค่ไม่มีunsigned long unsigned int
Christian Rau

4
@SethCarnegie: ในคอมพิวเตอร์ทั่วไปของฉันunsigned longคือ 64 บิตและunsigned int32 เป็นประเภทที่แตกต่างกันและไม่สามารถสันนิษฐานได้ว่าเหมือนกัน
Mike Seymour

2
@NicolBolas Like กล่าวว่า OP (และฉัน) ไม่รู้ว่าเป็นการเก็งกำไรเนื่องจากอาจมีเหตุผลที่ถูกต้องที่สมบูรณ์แบบสำหรับการฝังลึกลงไปในภาษาภายในของ C ++ แต่เนื่องจากคุณบอกว่าเป็นการคาดเดาฉันเดาว่าไม่มีเหตุผลเช่นนั้น แต่อีกครั้งบางทีผู้รับผิดชอบ C ++ 11 ยังสามารถตอบได้ นี่ไม่ใช่stouคำถาม"วะวาว่าไอ้นั่นอยู่ไหน" แต่เป็นคำถามที่ถามหาเหตุผลที่ชัดเจนสำหรับความไม่ลงรอยกันที่ชัดเจนนี้ หากคุณรู้ว่าไม่มีเหตุผลดังกล่าวก็โพสต์เป็นคำตอบ
Christian Rau

คำตอบ:


29

คำตอบตบเบา ๆ ส่วนใหญ่จะเป็นไปได้ว่าห้องสมุด C ไม่มีตรงกัน“ strtou” และ C ++ 11 ฟังก์ชั่นสตริงที่มีทั้งหมดห่อเพียงปกคลุมบาง ๆ รอบการทำงานห้องสมุด C นี้: std::sto*ฟังก์ชั่นกระจกstrto*และฟังก์ชั่นการใช้งานstd::to_stringsprintf


แก้ไข: ในฐานะที่เป็น KennyTM ชี้ให้เห็นทั้งสองstoiและstolใช้strtolเป็นฟังก์ชั่นแปลงต้นแบบ แต่ก็ยังคงลึกลับว่าทำไมในขณะที่ยังมีอยู่stoulการใช้งานที่ไม่มีความสอดคล้องกันstrtoulstou


14
คุณรู้หรือไม่ว่าเหตุใดคณะกรรมการ C ++ จึงตัดสินใจใช้แนวทาง C-ish เช่นนี้? สิ่งที่boost::lexical_cast<>()ดูเหมือนจะเป็นวิธีการทำ C ++ มากขึ้น
Paul Manta

2
รายละเอียดการใช้งานเหล่านี้กำหนดไว้เป็นมาตรฐานจริงหรือไม่
Lightness Races ใน Orbit

4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Effects: สองฟังก์ชั่นแรกเรียก strtol (str.c_str (), ptr, base) และสามฟังก์ชันสุดท้ายเรียก strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) และ strtoull (str.c_str (), ptr, base) ตามลำดับ
Mike Seymour

12
ไม่สำคัญว่ามาตรฐาน C ++ จะระบุว่า "ต้องนำไปใช้โดยการเรียก ... " เนื่องจากมาตรฐาน C ++ ยังคงมีกฎ global as-if: หากมาตรฐานระบุว่าstd::sto*ต้องนำไปใช้เป็นเครื่องห่อสำหรับฟังก์ชันไลบรารี C และ โปรแกรมที่ถูกต้องไม่สามารถบอกได้ว่าพวกเขาไม่ได้ใช้งานอย่างลับๆแตกต่างกันการใช้งานนั้นถูกต้อง

2
นอกประเด็นโดยสิ้นเชิงฉันคิดว่าเหตุผลที่เป็นประโยชน์ในการไม่ใช้ iostreams เช่น Boost / lexical_cast คือประสิทธิภาพที่แท้จริง ฉันเชื่อว่า iostreams แพ้ strtoul และอื่น ๆ ด้วยอัตรากำไรที่มาก
Kerrek SB

22

ฉันไม่รู้ว่าทำไมถึงstoiมีอยู่ แต่ไม่ใช่stouแต่ความแตกต่างเพียงอย่างเดียวระหว่างstoulและสมมุติstouคือการตรวจสอบว่าผลลัพธ์อยู่ในช่วงของunsigned:

unsigned stou(std::string const & str, size_t * idx = 0, int base = 10) {
    unsigned long result = std::stoul(str, idx, base);
    if (result > std::numeric_limits<unsigned>::max()) {
        throw std::out_of_range("stou");
    }
    return result;
}

(ในทำนองเดียวกันstoiก็คล้ายstolกับการตรวจสอบช่วงที่แตกต่างกัน แต่เนื่องจากมีอยู่แล้วจึงไม่จำเป็นต้องกังวลว่าจะใช้งานอย่างไร)


ความแตกต่างระหว่างstoiและstolหรือstolและstollเป็นเพียงการตรวจสอบช่วงเท่านั้น
Hossein

1
@Hossein: ระหว่างstoiและstolใช่ แต่stolและstollไม่แตกต่างกันเฉพาะในการตรวจสอบในช่วงที่พวกเขาเรียกฟังก์ชั่นที่แตกต่างกันห้องสมุด
Ben Voigt

0
unsigned long ulval = std::stoul(buf);
unsigned long mask = ~0xffffffffl;
unsigned int uival;
if( (ulval & mask) == 0 )
    uival = (unsigned int)ulval;
else {
    ...range error...
}

การใช้มาสก์เพื่อทำสิ่งนี้กับขนาดค่าที่คาดหวังเป็นบิตที่แสดงในมาสก์จะทำให้สิ่งนี้ใช้ได้กับความยาว 64 บิตเทียบกับ 32 บิต ints แต่ยังสำหรับความยาว 32 บิตเทียบกับ 32 บิต

ในกรณีของความยาว 64 บิต ~ 0xffffffffl จะกลายเป็น 0xffffffff00000000 และจะดูว่ามีการตั้งค่า 32 บิตบนสุดหรือไม่ ด้วยความยาว 32 บิต ~ 0xffffffffl จะกลายเป็น 0x00000000 และการตรวจสอบมาสก์จะเป็นศูนย์เสมอ

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