Why Is Std::Is_Pod Deprecated in C++20

Why is std::is_pod deprecated in C++20?

POD is being replaced with two categories that give more nuances. The c++ standard meeting in november 2017 had this to say about it:

Deprecating the notion of “plain old data” (POD). It has been replaced with two more nuanced categories of types, “trivial” and “standard-layout”. “POD” is equivalent to “trivial and standard layout”, but for many code patterns, a narrower restriction to just “trivial” or just “standard layout” is appropriate; to encourage such precision, the notion of “POD” was therefore deprecated. The library trait is_pod has also been deprecated correspondingly.

For simple data types use the is_standard_layout function, for trivial data types (such as simple structs) use the is_trivial function.

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

From the Microsoft documentation:

When a class or struct is both trivial and standard-layout, it is a POD (Plain Old Data) type.

It later describes literal types, including the following condition:

Additionally, all its non-static data members and base classes must be literal types and not volatile.

There is no mention of "volatile" anywhere else on the page.

This all matches what we find in the standard.

Therefore, I conclude it's a compiler bug.


getStuff() generates an error because it attempts to return a type that is not compatible with the C calling convention.

Actually, this is just a warning (C4190), which you could disable, if you wanted. Visual Studio on x86_64 only has one calling convention (described here). Your code will still work fine. VS is just warning you that the type won't work if you actually try to use it in C. extern "C" does not mean compiling as C.

However, it is true that getting this warning suggests the bug is indeed in the compiler, rather than simply in the implementation of std::is_pod.


Also, I would recommend avoiding POD terminology and the std::is_pod trait in new code, since they are 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++?

Anything that doesn't actually require the type to fit VS's definition of "POD", type trait notwithstanding, should be fine.

How do I use std::is_pod in a template argument?

You need to use std::enable_if to use the value from std::is_pod in a SFINAE context. That would look like

// only enable this template if Z is a pod type
template <class Z, std::enable_if_t<std::is_pod_v<Z>, bool> = true>
void x()
{
std::cout << "yep" << std::endl;
}

// only enable this template if Z is not a pod type
template <class Z, std::enable_if_t<!std::is_pod_v<Z>, bool> = true>
void x()
{
std::cout << "nope" << std::endl;
}

Do note that std::is_pod is deprecated in C++17 and has been removed from C++20.

What trait / concept can guarantee memsetting an object is well defined?

There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.

That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.

So you can't memset such an object and still get well-defined behavior from the object model.

Should we serialize std::chrono::duration class or is it P.O.D. (Plain Old Data) and no serialization is needed?

Your code "proves" only one thing: that the implementation you ran it on implemented duration such that it is trivially copyable and standard layout. Nothing in the standard requires it to be so, so any other implementation (including later versions of the same library) can freely change the rules.

Now, you can do some if constexpr/enable_if or similar gymnastics, so that if an implementation provides trivial copyability, you use that ability rather than "serializing" it. But you can't assume that this will always be the case (unless you are working in an environment where you know you will always use a particular library); you can merely take advantage of it where available.

What are POD types in C++?

POD stands for Plain Old Data - that is, a class (whether defined with the keyword struct or the keyword class) without constructors, destructors and virtual members functions. Wikipedia's article on POD goes into a bit more detail and defines it as:

A Plain Old Data Structure in C++ is an aggregate class that contains only PODS as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type.

Greater detail can be found in this answer for C++98/03. C++11 changed the rules surrounding POD, relaxing them greatly, thus necessitating a follow-up answer here.



Related Topics



Leave a reply



Submit