std::from_chars fails with a generic error when parsing a string of bits (base=2) as a signed 8-bit integer, whereas std::stoi parses the signed 8-bit integer without error.
Both blocks in the program below parse the same string of bits. The program ends by calling std::abort on the first assertion in the second block. std::stoi parses the same string of bits without error.
// Compile: g++ -std=c++17 -O0 -g main.cc -o main
#include <string>
#include <cassert>
#include <charconv>
#include <cstdint>
int main()
{
{
std::string bits = "10011100";
int base = 2;
std::int8_t num = std::stoi(bits.c_str(), nullptr, base);
assert(num == -100);
}
{
// Bug found in std::from_chars when type is int8_t and base=2.
std::string bits = "10011100";
int base = 2;
std::int8_t num;
auto [ptr, ec] = std::from_chars(bits.data(),
bits.data() + bits.size(),
num,
base);
assert(ec == std::errc()); // Calls std::abort.
assert(num == -100);
}
}
Output of running this program after compiling with g++ -std=c++17 -O0 -g main.cc -o main.
# ./main
main: main.cc:24: int main(): Assertion `ec == std::errc()' failed.
Aborted
>Solution :
10011100 in binary is 156 in decimal.
A signed 8-bit integer type is not able to hold that value (maximum is 127) and therefore std::from_chars will fail.
It doesn’t fail for std::stoi, because the value 156 is in range of int (which is at least 16bit wide).
If your intention is to interpret the bits as a two’s complement representation of an 8bit integer value, then you need to first parse it into a uint8_t, then cast to int8_t, assuming that the C++ implementation also uses two’s complement to represent int8_t. This is mandatory in C++20, but not C++17. If the implementation does not use the same representation as what you want to parse represents, then you need to do the conversion manually.