Tại sao không có std :: stou?


96

C ++ 11 đã thêm một số hàm chuyển đổi chuỗi mới:

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

Nó bao gồm stoi (chuỗi thành int), stol (chuỗi thành dài), stoul (chuỗi thành dài), stoul (chuỗi thành dài không dấu), stoull (chuỗi thành dài dài không dấu). Đáng chú ý khi không có nó là một hàm stou (chuỗi thành không dấu). Có một số lý do nó không cần thiết nhưng tất cả những người khác thì có?

liên quan: Không có hàm "st {short, unsigned short}" trong C ++ 11?


6
Câu hỏi của tôi được dự định là "có một số nhược điểm không rõ ràng của việc chỉ sử dụng stoul". Rõ ràng là điều đó sẽ gây rối với việc khởi tạo mẫu, nhưng có điều gì khác mà tôi không xem xét? Nhận xét về lý do tại sao nó bị loại bỏ sẽ là tốt nhưng thứ yếu.
David Stone

12
@NicolBolas Tôi không thể hiểu tại sao điều này không mang tính xây dựng. Đó là một câu hỏi hoàn toàn hợp lệ vì tôi không thể thấy bất kỳ lý do nào cho sự mâu thuẫn này và anwers có thể cung cấp thông tin chi tiết về một số lý do hợp lệ có thể tồn tại nhưng không phải là lý do rõ ràng cho nó.
Christian Rau

4
@SethCarnegie Chà, những gì nền tảng của bạn (và có thể là phần lớn các nền tảng) thực hiện không liên quan, bởi vì unsigned longchỉ là không unsigned int.
Christian Rau

4
@SethCarnegie: trên máy tính thông thường của tôi, unsigned longlà 64 bit và unsigned int32. Chúng là các loại khác nhau và không thể được coi là giống nhau.
Mike Seymour

2
@NicolBolas Như đã nói, OP (và tôi) không biết đó là suy đoán, vì có thể có một lý do hợp lệ hoàn hảo cho việc nó được chôn sâu trong nội bộ ngôn ngữ của C ++. Nhưng vì bạn nói đó là suy đoán, tôi đoán không có lý do nào như vậy. Nhưng một lần nữa, có lẽ một người chịu trách nhiệm về C ++ 11 vẫn có thể trả lời nó. Đây không phải là stoucâu hỏi "Wah wah, con chết tiệt đó ở đâu ", mà là một câu hỏi hỏi một lý do có thể xác định cho sự mâu thuẫn rõ ràng này. Nếu bạn biết không có lý do như vậy, thì hãy đăng nó như một câu trả lời.
Christian Rau

Câu trả lời:


29

Câu trả lời thú vị nhất sẽ là thư viện C không có “” tương ứng strtou, và các hàm chuỗi C ++ 11 đều chỉ là những lớp bao bọc mỏng manh xung quanh các hàm của thư viện C: Các std::sto*hàm nhân bản strto*và các std::to_stringhàm sử dụng sprintf.


Chỉnh sửa: Như KennyTM đã chỉ ra, cả hai stoistolsử dụng strtollàm chức năng chuyển đổi cơ bản, nhưng vẫn còn bí ẩn tại sao trong khi tồn tại stoulmà sử dụng strtoul, không có tương ứng stou.


14
Bạn có biết tại sao Ủy ban C ++ lại quyết định chọn cách tiếp cận C-ish như vậy không? Một cái gì đó giống như boost::lexical_cast<>()có vẻ giống như một cách hoạt động C ++ hơn.
Paul Manta

2
Các chi tiết triển khai này có thực sự được xác định tiêu chuẩn không?
Các cuộc đua ánh sáng trong quỹ đạo

4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Hiệu ứng: hai hàm đầu tiên gọi hàm strtol (str.c_str (), ptr, base) và ba hàm cuối cùng gọi strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) và strtoull (str.c_str (), ptr, base), tương ứng.
Mike Seymour

12
Không quan trọng liệu tiêu chuẩn C ++ có nói "phải được thực hiện bằng cách gọi ..." hay không, bởi vì tiêu chuẩn C ++ vẫn có quy tắc chung như thể: nếu tiêu chuẩn cho biết std::sto*phải được triển khai dưới dạng trình bao bọc cho các hàm thư viện C và một chương trình hợp lệ không thể nói rằng chúng không được triển khai bí mật theo cách khác, việc triển khai là hợp lệ.

2
Hoàn toàn lạc đề, tôi nghĩ lý do thực tế để không sử dụng iostreams như Boost / lexical_cast là hiệu suất tuyệt đối; Tôi tin rằng iostreams thua strtoul, vv với một biên độ đáng kể.
Kerrek SB

22

Tôi không biết tại sao lại stoitồn tại nhưng không tồn tại stou, nhưng sự khác biệt duy nhất giữa stoulgiả thuyết và giả thuyết stousẽ là kiểm tra xem kết quả có nằm trong phạm vi 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;
}

(Tương tự như vậy, stoicũng tương tự như stol, chỉ với một kiểm tra phạm vi khác; nhưng vì nó đã tồn tại, không cần phải lo lắng về cách triển khai chính xác.)


Sự khác biệt giữa stoistol, hoặc stolstollcũng chỉ là một kiểm tra phạm vi.
Hossein

1
@Hossein: Giữa stoistol, có. Nhưng stolstollkhông chỉ khác nhau trong phạm vi kiểm tra, chúng gọi các hàm thư viện khác nhau.
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...
}

Sử dụng mặt nạ để thực hiện việc này với kích thước giá trị dự kiến ​​tính bằng bit được biểu thị trong mặt nạ, sẽ làm cho điều này hoạt động cho độ dài 64 bit so với int 32 bit, nhưng cũng cho độ dài 32 bit so với int 32 bit.

Trong trường hợp độ dài 64 bit, ~ 0xffffffffl sẽ trở thành 0xffffffff00000000 và do đó sẽ xem có bất kỳ 32 bit hàng đầu nào được đặt hay không. Với độ dài 32 bit, nó ~ 0xffffffffl trở thành 0x00000000 và kiểm tra mặt nạ sẽ luôn bằng 0.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.