Home > Software engineering >  C std::string bug when adding size as string in map
C std::string bug when adding size as string in map

Time:10-09

I found Some thing on visual studio v143 tools std:c lastest is it bug or something

std::unordered_map<std::string, std::string> map;
std::string test_str = "1234567890123456789012345678901234567890123456789012345";//55 LEN String
map["test_len"] = test_str.length();
std::cout << map["test_len"]; // 7 on 55 len string

CodePudding user response:

In statement

map["test_len"] = test_str.length();

std::unordered_map::operator[] default-constructs a new std::string and returns a reference to it which is then assigned to a value of type size_type. This assignment invokes std::string::operator=(char) which interprets integer value 55 as ascii character 7.

This is a long standing usability bug in std::string interface. Examples of the bug:

std::string s = test_str.length(); // Compiler error.

std::string s2;
s2 = test_str.length(); // Compiles successfully, std::string interface bug.
s2 = true; // Compiles successfully, std::string interface bug.
s2 = std::ios_base::failbit; // Compiles successfully, std::string and std::ios_base interface bugs.

std::string s3{std::ios_base::failbit, 55, true, 'a'}; // Compiles successfully, std::string interface bug.
std::string s3 = {std::ios_base::failbit, 55, true, 'a'}; // Compiles successfully, std::string interface bug.

C 17 type-safe way to insert or assign a value into an associative container is:

map.insert_or_assign("test_len", test_str.length()); // Compiler error.
map.insert_or_assign("test_len", {std::ios_base::failbit, 55, true, 'a'}); // Compiler error.
map.insert_or_assign("test_len", std::to_string(test_str.length())); // Success.

std::unordered_map::insert_or_assign always uses direct-initialization of mapped value to avoid precisely this kind of silent unanticipated type conversion bugs when value type assignment operator has different semantics from its constructor, which breaks the engineering principle of least surprise.

CodePudding user response:

You try to put length() to a string -> string map. What you need instead is to put to_string() of it:

#include <unordered_map>
#include <string>
#include <iostream>

int main() {
    std::unordered_map<std::string, std::string> map;
    std::string test_str = "1234567890123456789012345678901234567890123456789012345";//55 LEN String
    map["test_len"] = std::to_string(test_str.length());
    std::cout << map["test_len"];
}

Note that std::string does have a ctor from a char, as in Maxim's answer, hence your code is not an error, just not what you expected it to be.

  • Related