std::num_ge...get::do_get(3)
πΈ NAME πΈ
okay so bestie, this is std::num_ge...get::do_get(3) from the C++ Standard Libary manual, and it's giving numeric-input main-character energy π
β¨
std::num_get::get, std::num_get::do_get β yep, both of them: std::num_get::get,std::num_get::do_get. periodt.
β¨ Synopsis β¨
public:
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
bool& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
long& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str, (since
C++11)
std::ios_base::iostate& err, long
long& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
unsigned short& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
unsigned int& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
unsigned long& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str, (since
C++11)
std::ios_base::iostate& err,
unsigned long long& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
float& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
double& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err, long
double& v ) const;
iter_type get( iter_type in, iter_type end,
std::ios_base& str,
std::ios_base::iostate& err,
void*& v ) const;
protected:
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
(1)
std::ios_base::iostate& err, bool& v ) const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v ) const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
(since
C++11)
std::ios_base::iostate& err, long long& v )
const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned short& v )
const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, unsigned int& v )
const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str, (2)
std::ios_base::iostate& err, unsigned long& v )
const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
(since
C++11)
std::ios_base::iostate& err,
unsigned long long& v
) const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, float& v ) const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, double& v ) const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long double& v )
const;
virtual iter_type do_get( iter_type in,
iter_type end, std::ios_base& str,
std::ios_base::iostate& err, void*& v ) const;
- Public member function β calls the member function
do_getof the most derived class. - The actual reading era β reads characters from the input iterator
inand generates the value of the type ofv, taking into account I/O stream formatting flags fromstr.flags(), character classification rules fromstd::use_facet<std::ctype<CharT>>(str.getloc()), and numeric punctuation characters fromstd::use_facet<std::numpunct<CharT>>(str.getloc()). This function is called by all formatted input stream operators such asstd::cin >> n;.
Conversion occurs in three stages:
π Stage 1: conversion specifier selection
- I/O format flags are obtained, as if by:
fmtflags basefield = (str.flags() & std::ios_base::basefield);
fmtflags boolalpha = (str.flags() & std::ios_base::boolalpha);
- If the type of
vis an integer type, the first applicable choice of the following five is selected:- If
basefield == oct, will use conversion specifier%o - If
basefield == hex, will use conversion specifier%X - If
basefield == 0, will use conversion specifier%i - If the type of
vis signed, will use conversion specifier%d - If the type of
vis unsigned, will use conversion specifier%u
- If
- For integer types, length modifier is added to the conversion specification if necessary:
hforshortandunsigned short,lforlongandunsigned long,llforlong longandunsigned long long(since C++11). - If the type of
visfloat, will use conversion specifier%g. - If the type of
visdouble, will use conversion specifier%lg. - If the type of
vislong double, will use conversion specifier%Lg. - If the type of
visvoid*, will use conversion specifier%p. - If the type of
visboolandboolalpha == 0, proceeds as if the type ofvislong, except for the value to be stored invin stage 3. - If the type of
visboolandboolalpha != 0, the following replaces stages 2 and 3:- Successive characters obtained from the input iterator
inare matched against the character sequences obtained fromstd::use_facet<std::numpunct<CharT>>(str.getloc()).falsename()andstd::use_facet<std::numpunct<CharT>>(str.getloc()).truename()only as necessary as to identify the unique match. The input iteratorinis compared toendonly when necessary to obtain a character. - If the target sequence is uniquely matched,
vis set to the correspondingboolvalue. Otherwisefalseis stored invandstd::ios_base::failbitis assigned toerr. If unique match could not be found before the input ended (in == end),err |= std::ios_base::eofbitis executed.
- Successive characters obtained from the input iterator
π¦ Stage 2: character extraction
- If
in == end, stage 2 is terminated immediately, no further characters are extracted. - The next character is extracted from
inas if bychar_type ct = *in;:- If the character matches one of
"0123456789abcdefxABCDEFX+-"(until C++11)"0123456789abcdefpxABCDEFPX+-"(since C++11), widened to the locale'schar_typeas if bystd::use_facet<std::ctype<CharT>>(str.getloc()).widen(), it is converted to the correspondingchar. - If the character matches the decimal point separator (
std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point()), it is replaced by'.'. - If the character matches the thousands separator (
std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep()) and the thousands separation is in use (as determined bystd::use_facet<std::numpunct<CharT>>(str.getloc()).grouping().length() != 0), then if the decimal point'.'has not yet been accumulated, the position of the character is remembered, but the character is otherwise ignored. If the decimal point has already been accumulated, the character is discarded and stage 2 terminates. - In any case, the check is made whether the
charobtained from the previous steps is allowed in the input field that would be parsed bystd::scanfgiven the conversion specifier selected in stage 1. If it is allowed, it is accumulated in a temporary buffer and stage 2 repeats. If it is not allowed, stage 2 terminates.
- If the character matches one of
π Stage 3: conversion and storage
- The sequence of
chars accumulated in stage 2 is converted to a numeric value: - The input is parsed according to the rules of
std::scanf. (until C++11) - The input is parsed as if by:
std::strtollfor signed integerv,std::strtoullfor unsigned integerv, (since C++11)std::strtofforfloatv,std::strtodfordoublev, orstd::strtoldforlong doublev.
- If the conversion function fails to convert the entire field, the value
0is stored inv. - If the type of
vis a signed integer type and the conversion function results in a positive or negative value too large to fit in it, the most positive or negative representable value is stored inv, respectively. - If the type of
vis an unsigned integer type and the conversion function results in a value that does not fit in it, the most positive representable value is stored inv. - In any case, if the conversion function fails
std::ios_base::failbitis assigned toerr. - Otherwise, the numeric result of the conversion is stored in
v.- If the type of
visboolandboolalphais not set, then if the value to be stored is0,falseis stored, if the value to be stored is1,trueis stored, for any other valuestd::ios_base::failbitis assigned toerrandtrueis stored.
- If the type of
- After this, digit grouping is checked. if the position of any of the thousands separators discarded in stage 2 does not match the grouping provided by
std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping(),std::ios_base::failbitis assigned toerr. - If stage 2 was terminated by the test
in == end,err |= std::ios_base::eofbitis executed to set the eof bit.
π Return value π
in
π NOTES π
okay so these are the little historical receipts, bestie β stuff that used to be broken before the committee fixed it. ngl they're kind of iconic.
- Before the resolutions of LWG issue 23 and LWG issue 696,
vwas left unchanged if an error occurs. - Before the resolution of LWG issue 221, strings representing hexadecimal integers (e.g.
"0xA0") were rejected bydo_get(int)even if they are valid input tostrtolbecause stage 2 filters out characters'X'and'x'. π imagine rejecting a whole valid hex string, couldn't be stage 2. - Before the resolution of LWG issue 1169, converting a negative number string into an unsigned integer might produce zero (since the value represented by the string is smaller than what the target type can represent).
- Before the resolution of LWG issue 2381, strings representing hexadecimal floating-point numbers with exponents (e.g.
"0x1.23p-10") were rejected bydo_get(double)even if they are valid input tostrtodbecause stage 2 filters out characters'P'and'p'. (since C++11) - The strings representing infinity or not-a-number (e.g.
"NaN"and"inf") are rejected bydo_get(double)even if they are valid input tostrtodbecause stage 2 filters out characters such as'N'or'i'.
π«Ά lowkey important: that last one is still the behaviour, no LWG issue saving you here. stage 2 is out here filtering'N'and'i'and your"NaN"is just not making it through, periodt.
πΈ EXAMPLE πΈ
an implementation of operator>> for a user-defined type. yes she's custom, yes she slays. π
// Run this code
#include <iostream>
#include <iterator>
#include <locale>
struct base { long x; };
template<class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT, Traits>& is, base& b)
{
std::ios_base::iostate err = std::ios_base::goodbit;
try // setting err could throw
{
typename std::basic_istream<CharT, Traits>::sentry s(is);
if (s) // if stream is ready for input
std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x);
}
catch (std::ios_base::failure& error)
{
// handle the exception
}
return is;
}
int main()
{
base b;
std::cin >> b;
}
like, the sentry is doing the vibe check on your stream first (is it ready for input?), then use_facet pulls the num_get facet out of the locale and calls .get β and the try/catch is there because setting err could throw. main character error handling fr fr. β¨
π DEFECT REPORTS π
The following behavior-changing defect reports were applied retroactively to previously published C++ standards. (aka: the glow-ups that got applied to old standards after the fact, retroactively, iykyk π )
- LWG 17 β applied to C++98. published: the process of parsing text boolean values was errornous. corrected: corrected.
- LWG 18 β applied to C++98. published: the overload of
gettakingbool&value was missing. corrected: added. - LWG 23 β applied to C++98. published: overflowing input resulted in undefined behavior. corrected: overflow handled.
- LWG 154 β applied to C++98. published: the conversion specifier for
doublewas%lg. corrected: changed to%g(same asfloat). - LWG 221 β applied to C++98. published:
do_getdid not parse'x'and'X'whilestrtolparsed them. corrected: made'x'and'X'parsed. - LWG 275 β applied to C++98. published:
gethad an overload takingshort&value instead offloat&. corrected: corrected. - LWG 358 β applied to C++98. published: thousand separators after the decimal point were ignored. corrected: stage 2 is terminated if encountered.
- LWG 696 β applied to C++98. published: the result was unchanged on conversion failure. corrected: set to zero.
- LWG 1169 β applied to C++98. published: overflow handling was inconsistent between floating-point types. corrected: made consistent with
strtof/strtod. - LWG 2381 β applied to C++11. published:
do_getdid not parse'p'and'P'whilestrtodparsed them. corrected: made'p'and'P'parsed.
π not LWG 154 changing the specifier and the "corrected" column just being the one word corrected β she said "fixed, next question."
π¦ SEE ALSO π¦
operator>>β extracts formatted data (public member function ofstd::basic_istream<CharT,Traits>)
and that's the whole page, bestie!! you made it to the end, so proud of you π«Άπ this was std::num_ge...get::do_get(3), straight from cppreference.com, dated 2024.06.10 β go forth and parse responsibly, mwah π
β¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms