使用 clang 对 std::atomic 函数的调用不明确

Ambiguous call to std::atomic function using clang

我正在尝试用 clang 编译我的代码,我之前使用的是 g++。

我在编译以下代码时遇到错误:

#include <atomic>

typedef void (*my_func) ();
int main(int argc, char** argv)
{
  std::atomic<my_func> _func;
  _func();
  return 0;
}

错误是:

a.cpp:23:3: error: call to object of type 'std::atomic<my_func>' is ambiguous
  _func();
  ^~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/atomic:304:7: note: conversion candidate of type 'void (*)()'
      operator __pointer_type() const noexcept
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/atomic:307:7: note: conversion candidate of type 'void (*)()'
      operator __pointer_type() const volatile noexcept
      ^
1 error generated.

这不是我的代码,它是我需要维护的遗留代码。在实际代码中,_func 是一个 class 成员,有一个 setter 和一个 getter,据我了解,他打算保护它,以便在他打算调用它时不修改它。

编辑: 我正在使用 clang3.6(clang3.7 上的相同错误)和 g++ 以及 std::atomic 4.8.

如果您能够编辑这些来源,我建议您将函数调用替换为 _func.load()(); 之类的内容。此代码本质上做同样的事情,但允许您避免模棱两可的调用。

MS 的 Visual C++ 编译器中存在同样的问题。 我想这是原子接口设计的普遍问题。

如果问题是'how to compile the code on CLang',答案很简单:

#include <atomic>

typedef void (*my_func) (int );
int main()
{
  std::atomic<my_func> _func;
  (*_func)(42);
  return 0;
}

原子类型上没有定义 operator(),因此编译器必须执行类型转换 - 有两个选项。另一个修复方法是使 _func 易变:volatile std::atomic<my_func> _func;,但这可读性和明显性要差得多。