#include <cstdint>
#include <type_traits>
extern "C"
{
struct thread_shared_struct
{
volatile uint32_t ccr;
};
struct thread_shared_struct getStuff();
}
static_assert(std::is_pod<thread_shared_struct>::value, "thread_shared_struct isn't a POD");
int main(int argc, char** argv)
{
thread_shared_struct m = getStuff();
return 0;
}
当然,这个示例没有多大意义,但它是从更大的代码库中最小化我的问题的再现。
使用 GCC(主干)和 Clang(主干),效果很好。
使用 MSVC(x64、19.22),static_assert 失败并且 getStuff() 生成错误,因为它尝试返回与 C 调用约定不兼容的类型。
如果删除“ volatile ”,则一切正常。
MSVC 认为 thread_shared_struct 不是 POD 类型是错误的吗?
extern“C”部分位于 C header 中,需要保持原样。我如何在 C++ 中使用它?
最佳答案
来自the Microsoft documentation :
When a class or struct is both trivial and standard-layout, it is a POD (Plain Old Data) type.
稍后描述文字类型,包括以下条件:
Additionally, all its non-static data members and base classes must be literal types and not volatile.
页面上的其他任何地方都没有提到“ volatile ”。
这一切都符合我们发现的in the standard .
因此,我断定这是一个编译器错误。
getStuff() generates an error because it attempts to return a type that is not compatible with the C calling convention.
实际上,这只是一个警告 (C4190),如果您愿意,您可以将其禁用。 x86_64 上的 Visual Studio 只有一种调用约定(描述为 here )。您的代码仍然可以正常工作。 VS 只是警告您,如果您实际尝试在 C 中使用该类型,该类型将无法工作。 extern "C"
并不意味着编译为 C。
但是,收到此警告确实表明该错误确实存在于编译器中,而不仅仅是存在于 std::is_pod
的实现中。
此外,我建议在新代码中避免使用 POD 术语和 std::is_pod
特征,因为它们是 deprecated from C++20 .
The extern "C" part is in a C header that needs to stay as is. How could I use it from C++?
任何实际上不需要类型符合 VS 的“POD”定义的东西,尽管有类型特征,应该没问题。
关于c++ - 根据 MSVC,具有 volatile 成员的结构不再是 POD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59103157/