如何用g ++打印__int128?

per*_*ror 37 c++ iostream int128

__int128在我的C++程序中使用GCC内置类型的一些东西,没有什么真正重要的,至少不足以证明仅仅为此使用BigInt库,并且足以防止完全删除它.

当我遇到我的课程的打印部分时,我的问题出现了,这是一个最小的例子:

#include <iostream>

int main()
{
  __int128 t = 1234567890;

  std::cout << t << std::endl;

  return t;
}
Run Code Online (Sandbox Code Playgroud)

注释掉这一std::cout行会使这段代码很好地编译g++,但是它会导致以下错误信息:

int128.c: In function ‘int main()’:
int128.c:7:13: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘__int128’)
   std::cout << t << std::endl;
             ^
int128.c:7:13: note: candidates are:
In file included from /usr/include/c++/4.9/iostream:39:0,
                 from int128.c:1:
/usr/include/c++/4.9/ostream:108:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] <near match>
       operator<<(__ostream_type& (*__pf)(__ostream_type&))
       ^
/usr/include/c++/4.9/ostream:108:7: note:   no known conversion for argument 1 from ‘__int128’ to ‘std::basic_ostream<char>::__ostream_type& (*)(std::basic_ostream<char>::__ostream_type&) {aka std::basic_ostream<char>& (*)(std::basic_ostream<char>&)}’
/usr/include/c++/4.9/ostream:117:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>; std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>] <near match>
       operator<<(__ios_type& (*__pf)(__ios_type&))
       ^
/usr/include/c++/4.9/ostream:117:7: note:   no known conversion for argument 1 from ‘__int128’ to ‘std::basic_ostream<char>::__ios_type& (*)(std::basic_ostream<char>::__ios_type&) {aka std::basic_ios<char>& (*)(std::basic_ios<char>&)}’
/usr/include/c++/4.9/ostream:127:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] <near match>
       operator<<(ios_base& (*__pf) (ios_base&))
       ^
/usr/include/c++/4.9/ostream:127:7: note:   no known conversion for argument 1 from ‘__int128’ to ‘std::ios_base& (*)(std::ios_base&)’
/usr/include/c++/4.9/ostream:166:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(long __n)
       ^
/usr/include/c++/4.9/ostream:170:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(unsigned long __n)
       ^
/usr/include/c++/4.9/ostream:174:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(bool __n)
       ^
In file included from /usr/include/c++/4.9/ostream:609:0,
                 from /usr/include/c++/4.9/iostream:39,
                 from int128.c:1:
/usr/include/c++/4.9/bits/ostream.tcc:91:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char; _Traits = std::char_traits<char>]
     basic_ostream<_CharT, _Traits>::
     ^
In file included from /usr/include/c++/4.9/iostream:39:0,
                 from int128.c:1:
/usr/include/c++/4.9/ostream:181:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(unsigned short __n)
       ^
In file included from /usr/include/c++/4.9/ostream:609:0,
                 from /usr/include/c++/4.9/iostream:39,
                 from int128.c:1:
/usr/include/c++/4.9/bits/ostream.tcc:105:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char; _Traits = std::char_traits<char>]
     basic_ostream<_CharT, _Traits>::
     ^
In file included from /usr/include/c++/4.9/iostream:39:0,
                 from int128.c:1:
/usr/include/c++/4.9/ostream:192:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(unsigned int __n)
       ^
/usr/include/c++/4.9/ostream:201:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(long long __n)
       ^
/usr/include/c++/4.9/ostream:205:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(unsigned long long __n)
       ^
/usr/include/c++/4.9/ostream:220:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(double __f)
       ^
/usr/include/c++/4.9/ostream:224:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(float __f)
       ^
/usr/include/c++/4.9/ostream:232:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
       operator<<(long double __f)
       ^
/usr/include/c++/4.9/ostream:245:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] <near match>
       operator<<(const void* __p)
       ^
/usr/include/c++/4.9/ostream:245:7: note:   no known conversion for argument 1 from ‘__int128’ to ‘const void*’
In file included from /usr/include/c++/4.9/ostream:609:0,
                 from /usr/include/c++/4.9/iostream:39,
                 from int128.c:1:
/usr/include/c++/4.9/bits/ostream.tcc:119:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>] <near match>
     basic_ostream<_CharT, _Traits>::
     ^
/usr/include/c++/4.9/bits/ostream.tcc:119:5: note:   no known conversion for argument 1 from ‘__int128’ to ‘std::basic_ostream<char>::__streambuf_type* {aka std::basic_streambuf<char>*}’
In file included from /usr/include/c++/4.9/iostream:39:0,
                 from int128.c:1:
/usr/include/c++/4.9/ostream:493:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char) [with _Traits = std::char_traits<char>]
     operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
     ^
/usr/include/c++/4.9/ostream:488:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char) [with _Traits = std::char_traits<char>]
     operator<<(basic_ostream<char, _Traits>& __out, signed char __c)
     ^
/usr/include/c++/4.9/ostream:482:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char) [with _Traits = std::char_traits<char>]
     operator<<(basic_ostream<char, _Traits>& __out, char __c)
     ^
/usr/include/c++/4.9/ostream:476:5: note: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) [with _CharT = char; _Traits = std::char_traits<char>]
     operator<<(basic_ostream<_CharT, _Traits>& __out, char __c)
     ^
Run Code Online (Sandbox Code Playgroud)

是的,我知道,解释的很多方面__int128都没有得到妥善处理......

是否有一种简单的方法__int128可以iostream像其他任何数字类型一样进行打印?

编辑:对于仍然混淆C和C++的人,是的,我读了一个问题:如何使用gcc打印__uint128_t数字?但是,这是针对C而不是我现在要求的C++.

Jam*_*nze 31

如果您不需要任何花哨的格式化选项,编写自己的<<运算符是微不足道的.在形式上,我怀疑编写一个__int128_t将被视为未定义的行为,但实际上,我认为它会起作用,直到库开始提供它的实际支持(此时,您将退出转换运算符).

无论如何,类似下面的东西应该工作:

std::ostream&
operator<<( std::ostream& dest, __int128_t value )
{
    std::ostream::sentry s( dest );
    if ( s ) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[ 128 ];
        char* d = std::end( buffer );
        do
        {
            -- d;
            *d = "0123456789"[ tmp % 10 ];
            tmp /= 10;
        } while ( tmp != 0 );
        if ( value < 0 ) {
            -- d;
            *d = '-';
        }
        int len = std::end( buffer ) - d;
        if ( dest.rdbuf()->sputn( d, len ) != len ) {
            dest.setstate( std::ios_base::badbit );
        }
    }
    return dest;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这只是一个快速的临时修复,直到g ++库支持该类型.它依赖于2的补码,包括溢出,__int128_t但是,如果不是这样的话,我会非常惊讶(正式来说,它是未定义的行为).如果没有,你需要修复初始化 tmp.当然,它不处理任何格式化选项; 你可以根据需要添加.(处理填充和 adjustfield正确可能是非平凡的.)

  • "但如果不是这样的话,我会感到非常惊讶" - gcc因为没有发生签名溢出的假设而进行积极优化而闻名,所以我不会像你一样惊讶.像` - (value + 1)+ __uint128_t(1)`这样的东西应该是有效的,并且很有可能被优化器发现等同于`-value`的环绕版本. (2认同)

Tem*_*Rex 17

我会建议不要超载operator<<__int128_t.原因是无论何时你看到cout << x某种整数类型,你都希望各种类型的操纵者都喜欢std::hex或者std::setw也应该工作.超载运营商时最重要的指导原则是:"像投注那样做".

作为替代方案,我建议使用decimal_string(__int128_t)您可以cout << decimal_string(x);在代码中使用的函数.对于字符串转换,您可以使用任何与C相关的Q&A中的算法.这清楚地表明您有128位整数的特殊代码.只要标准库升级到128位支持,您就可以删除它(这grep对于这些功能来说很容易).