[英]Atomic function pointer call compiles in gcc, but not in clang and msvc
When calling function from an atomic function pointer, like:从原子 function 指针调用 function 时,如:
#include <atomic>
#include <type_traits>
int func0(){ return 0; }
using func_type = std::add_pointer<int()>::type;
std::atomic<func_type> f = { func0 };
int main(){
f();
}
gcc doesn't complain at all, while clang and msvc have problem with call f()
: gcc 根本没有抱怨,而 clang 和 msvc 在调用
f()
时有问题:
Clang additionally specifies possible call candidates to be: Clang 还指定可能的呼叫候选者为:
operator __pointer_type() const noexcept
operator __pointer_type() const volatile noexcept
It seems like this difference in volatility is confusing for clang and msvc, but not gcc.似乎这种波动性差异对 clang 和 msvc 造成了混淆,但对 gcc 却没有。
When call is changed from f()
to f.load()()
, the code works in all abovementioned compilers.当调用从
f()
更改为f.load()()
时,代码适用于所有上述编译器。 Which is all the more confusing, since both load()
and operator T()
are said to have const
and const volatile
overloads - if implicit conversion doesn't work, I'd expect load()
not to work as well.这更令人困惑,因为据说
load()
和operator T()
都具有const
和const volatile
重载——如果隐式转换不起作用,我预计load()
也不会起作用。 Are the rules somehow different within implicit conversions (versus member calls)?隐式转换(相对于成员调用)中的规则是否有所不同?
So, is gcc wrong to accept that code?那么,gcc 接受该代码是错误的吗? Are clang and msvc wrong to error out?
clang 和 msvc 是不是都错报错了? Any other combination of being wrong or right?
任何其他错误或正确的组合?
This is mostly a theoretical question, but if there is some better way to have an atomic function pointer, I'd like to know.这主要是一个理论问题,但如果有更好的方法来获得原子 function 指针,我想知道。
Clang and MSVC are correct. Clang 和 MSVC 是正确的。
For each conversion function to a function pointer of the class, a so-called surrogate call function is added to overload resolution, which if chosen would first convert the object via this operator overload to a function pointer and then call the function via the function pointer. For each conversion function to a function pointer of the class, a so-called surrogate call function is added to overload resolution, which if chosen would first convert the object via this operator overload to a function pointer and then call the function via the function pointer . This is explained in [over.call.object]/2 .
这在[over.call.object]/2中有解释。
However, the surrogate call function does not translate the cv-qualifiers of the conversion operator in any way.但是,代理调用 function 不会以任何方式转换转换运算符的 cv 限定符。 So, since
std::atomic
has a conversion operator which is volatile
and one which is not, there will be two indistinguishable surrogate call functions.因此,由于
std::atomic
有一个转换运算符,一个是volatile
一个不是,因此将有两个无法区分的代理调用函数。 These are also the only candidates since std::atomic
doesn't have any actual operator()
and so overload resolution must always be ambiguous.这些也是唯一的候选者,因为
std::atomic
没有任何实际的operator()
并且因此重载决策必须始终是模棱两可的。
There is even a footnote in the standard mentioning that this can happen, see [over.call.object]/footnote.120 .标准中甚至有一个脚注提到这可能发生,请参阅[over.call.object]/footnote.120 。
With a direct call to .load()
the volatile
-qualifier will be a tie-breaker in overload resolution, so this issue doesn't appear.通过直接调用
.load()
, volatile
-qualifier 将成为重载解决方案中的决胜局,因此不会出现此问题。
With (*f)()
overload resolution on the (built-in) operator*
with the function pointer type as parameter is performed.使用
(*f)()
对(内置) operator*
执行重载决策,指针类型为 function 作为参数。 There are two implicit conversion sequences via the two conversion functions.通过两个转换函数有两个隐式转换序列。 The standard isn't very clear on it, but I think the intention is that this doesn't result in an ambiguous conversion sequence (which would also imply ambiguous overload resolution when it is chosen).
标准对此不是很清楚,但我认为其意图是这不会导致不明确的转换序列(这也意味着在选择时不明确的重载解析)。 Instead I think it is intended that the rules for initialization by conversion function are applied to select only one of the conversions, which would make it unambiguously the
volatile
-qualified one.相反,我认为通过转换 function 进行初始化的规则仅应用于 select 转换之一,这将使它明确地成为
volatile
限定的转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.