当我用愚者的128位类型调用abs()
时,我得到了编译器错误。我的代码行如下所示:
__extension__ using int128_t = __int128;
int128_t mantissa_;
// Other code
using namespace std;
int128_t temp = abs(mantissa_);
我在本地遇到的错误是:
error: call of overloaded ‘abs(const int128_t&)’ is ambiguous
int128_t temp = abs(mantissa_);
/usr/include/stdlib.h:840:12: note: candidate: ‘int abs(int)’
840 | extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur;
/usr/include/c++/11/bits/std_abs.h:56:3: note: candidate: ‘long int std::abs(long int)’
56 | abs(long __i) { return __builtin_labs(__i); }
| ^~~
/usr/include/c++/11/bits/std_abs.h:61:3: note: candidate: ‘long long int std::abs(long long int)’
61 | abs(long long __x) { return __builtin_llabs (__x); }
| ^~~
/usr/include/c++/11/bits/std_abs.h:71:3: note: candidate: ‘constexpr double std::abs(double)’
71 | abs(double __x)
| ^~~
/usr/include/c++/11/bits/std_abs.h:75:3: note: candidate: ‘constexpr float std::abs(float)’
75 | abs(float __x)
| ^~~
/usr/include/c++/11/bits/std_abs.h:79:3: note: candidate: ‘constexpr long double std::abs(long double)’
79 | abs(long double __x)
所以它不考虑我的超载(如下)作为候选人?
namespace std
{
__extension__ using int128_t = __int128;
int128_t abs(int128_t x)
{
return x < 0 ? x * -1 : x; // Not ideal but no builtin for 128
}
}
过载是否正确?
然而,当我模拟Godbolt中的一个例子时,即使没有重载abs()
,它也能很好地编译:
https://godbolt.org/z/P8T1fGxcK
#include <iostream>
__extension__ using int128_t = __int128;
struct Decimal
{
Decimal(int128_t q) : mantissa_(q)
{
volatile int128_t x = abs(mantissa_); // How is this compiling?
std::cout << "ctor" << std::endl;
}
int128_t mantissa_;
};
int main()
{
Decimal dec(-6);
}
Godbolt使用的是像Abseil这样的库吗,他们提供了一个函数,这就是为什么它在编译?
1条答案
按热度按时间q0qdq0h21#
tl; d文件
移除
using namespace std;
或直接呼叫内建(__int128 temp = __builtin_abs(mantissa_);
)请注意,
__int128
是gcc特定的compiler extension(因此代码不可移植)为什么神箭能用
愚者将自动地将一组通用C函数视为内置函数:
6.59 Other Built-in Functions Provided by GCC
除非指定
-fno-builtin
(或为个别函式指定-fno-builtin-function
),否则ISO C90函式abort
、abs
、acos
、[...]、vprintf
和vsprintf
都会被辨识为内建函式。所有这些函式都有以__builtin_
为前置词的Map版本。所以当你编译一个类似下面的程序时,对
abs
的调用会自动被解释为__builtin_abs
:godbolt
这些函数的内置变体*支持
__int128
,因此可以正常工作。请注意,这个内建转换ONLY在重载解析确定
abs(foo)
将调用c函数abs
的情况下有效,ONLY如果您在没有-fno-builtin
的情况下进行编译。例如,
abs
-std::abs
-的c++变体将NOT转换为它的内置等效项,因此不会编译(_int128
没有重载):godbolt
代码示例无法工作的原因
您的代码示例包含
using namespace std;
-这将使std::abs
进入作用域,从而防止将abs(mantissa_)
调用视为内置函数(由于std::abs
没有__int128
的重载,您将得到一个模糊的函数调用错误)要实现这一点,您基本上有两种选择:
using namespace std;
,而要依赖gcc提供的内置转换,例如: