根据 MSVC,具有易失性成员的结构不再是 POD

Struct with a volatile member no longer a POD according to MSVC

#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;
}

this code on godbolt

当然,这个例子没有多大意义,但它是从更大的代码库中对我的问题的最小复制。

对于 GCC(主干)和 Clang(主干),这工作正常。

对于 MSVC (x64, 19.22),static_assert 失败并且 getStuff() 生成错误,因为它试图 return 一个与 C 调用约定不兼容的类型。

如果删除 "volatile",一切正常。

MSVC 认为 thread_shared_struct 不是 POD 类型是不是错了?

extern "C" 部分在 C 头文件中,需要保持原样。我如何从 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),您可以根据需要将其禁用。 Visual Studio on x86_64 只有一个调用约定(描述为 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" 的定义,尽管有类型特征,应该没问题。