I have the following code, which doesn't compile with x86_64 GCC 13:
#include <iostream>
#include <stdfloat>
int main() {
std::cout << std::float128_t{1} << '\n';
}
This gives me the following error:
<source>: In function 'int main()':
<source>:5:15: error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'std::float128_t' {aka '_Float128'})
5 | std::cout << std::float128_t{1} << '\n';
| ~~~~~~~~~ ^~ ~~~~~~~~~~~~~
| | |
| | std::float128_t {aka _Float128}
| std::ostream {aka std::basic_ostream<char>}
The listed ambiguous overloads are:
operator<<(long)
operator<<(unsigned long)
operator<<(bool)
- ...
Surprisingly, operator<<(float)
and other floating point types aren't listed.
I've checked the compiler support page for C++23, and this feature should be supported:
C++23 features | Paper(s) | libstdc++ | libc++ | MVSV STL |
---|---|---|---|---|
Standard names and library support for extended floating-point types |
P1467R9 | 13 | 19.37** |
See C++23 compiler support page
Am I misunderstanding something? Is cppreference wrong and extended floating-point types aren't fully supported yet?
How do I print a std::float128_t
without third-party libraries?
operator<<(std::float128_t)
is optionalNone of the
operator<<
overloads for extended floating-point types from<stdfloat>
are guaranteed to exist. Forstd::float128_t
it is quite common that this isn't the case. On x86_64:long double
is typically an 80-bit floating point type, andstd::float128_t
is a quadruple precision IEEE-754 floating-point type.This means that
std::float128_t
has a greater conversion rank1) thanlong double
. As a result,operator<<(std::float128_t)
is optional:- [ostream.formatted]/[ostream.inserters.arithmetic] §5
GCC isn't required to support it, and you should consider alternatives to
operator<<
when printing extended floating point types.Alternatives
This solution currently works, and is guaranteed to work. The
std::formatter
for extended floating-point types is implemented usingstd::to_chars
, which is required to support all arithmetic types.This solution doesn't work yet because libstdc++ doesn't implement the
<print>
header yet. However, once it does, this will also work, becausestd::println
also usesstd::formatter
.If
std::format
works, why isoperator<<
not supported?The proposal paper answers this question:
- P1467r9 §iostream
1) The conversion rank is greater because
std::float128_t
can represent more values thanlong double
, see [conv.rank] §2.