7
#include <iostream>

struct A {
  const int test_;
};

static_assert(std::is_pod<A>::value, "must be POD type");

int main()
{
    std::cout<<"Hello World";
    return 0;
}

On Clang and GCC std::is_pod<A>::value is true, while on ICC and MSVC it is false.

If const int test_; is replaced with either int test_; or const int* test_ then it also passes on ICC and MSVC.

What does the standard say?

matthias_buehlmann
  • 4,641
  • 6
  • 34
  • 76

3 Answers3

4

N4659

12/10

A POD struct is a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types).

For trivial

12/6

A trivial class is a class that is trivially copyable and has one or more default constructors

There is no available default constructor.

Further, for trivially copyable, the requirements include

12/6.2

that has at least one non-deleted copy constructor, move constructor, copy assignment operator, or move assignment operator

Since you include a const int, it's not trivially copyable (no assignment operators), so it is not a pod

^ I was wrong, it is copyable by having the constructors. I misread the "or" as "and"

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • 1
    I think you took a wrong turn here. A is *trivially copyable* because having just one copy constructor is sufficient to satisfy *at least one non-deleted copy constructor, move constructor, copy assignment operator, or move assignment operator*. The real problem is that the only implicitly declared default constructor is considered deleted. – user7860670 Jun 08 '21 at 18:47
  • @user7860670 you're right, updated thanks. – Ryan Haining Jun 08 '21 at 18:52
2

One of the requirements for POD type is to be a trivial type.

[class]
10 A POD struct 109 is a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). where trivial type

while trivial is defined in the same section as

6 A trivial class is a class that is trivially copyable and has one or more default constructors (15.1), all of which are either trivial or deleted and at least one of which is not deleted.

Since A has a field with const-qualifier which requires mandatory initialization, its implicitly declared default constructor is deleted. Therefore A is not trivial type and not a POD type. So VS and ICC are correct here. But it is probably not a big deal since POD trait became deprecated in C++20 and should be avoided in code using preceding standards.

user7860670
  • 35,849
  • 4
  • 58
  • 84
-2

You can find an explanation of what is_pod tests for and what it does not test for here: https://en.cppreference.com/w/cpp/types/is_pod A description of what PODTypes are is here: https://en.cppreference.com/w/cpp/named_req/PODType

To meet the test of POD, the type has to be:

both trivial and standard-layout

TrivialType is defined here: https://en.cppreference.com/w/cpp/named_req/TrivialType

Standard Layout Type here: https://en.cppreference.com/w/cpp/named_req/StandardLayoutType

TrivialType further defines two requirements:

  • TriviallyCopyable
  • If the type is a class type or array thereof, the class has one or more eligible default constructors, all of which are trivial.

Trivially Copyable is defined here: https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable

Based on this: http://www.cplusplus.com/reference/type_traits/is_trivially_copyable/ and Does a c++ struct have a default constructor?, it is clear that since implicit constructors are used, the struct is trivially copyable. Also see: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf page 41.

Since no constructor is defined, there is an implicit default constructor, therefore satisfying both requirements of a Trivial Type

Standard Layout requirements:

  • All non-static data members have the same access control
  • Has no virtual functions or virtual base classes
  • Has no non-static data members of reference type
  • All non-static data members and base classes are themselves standard layout types
  • Has no two (possibly indirect) base class subobjects of the same type
  • Has all non-static data members and bit-fields declared in the same class (either all in the derived or all in some base)
  • None of the base class subobjects has the same type as: for non-union types, as the first non-static data member (see empty base optimization), and, recursively, the first non-static data member of that data member if it has non-union class type, or all non-static data members of that data member if it has union type, or an element of that data member if it has array type, etc.

Therefore it has a standard layout as well.

Therefore, being of standard layout and trivial, the struct should be considered POD.

  • Updated to more clearly answer the question – Beenish Khurshid Jun 08 '21 at 19:36
  • Do you mean default destructor @TedLyngmo? A default destructor which implicitly calls delete is still a default destructor. – Beenish Khurshid Jun 08 '21 at 19:51
  • No, I mean that there is no default constructor because it's been implicitly `delete`d by all the mentioned implementations. – Ted Lyngmo Jun 08 '21 at 19:53
  • This stackoverflow question seems to differ in opinion: https://stackoverflow.com/questions/8280023/does-a-c-struct-have-a-default-constructor Maybe I am misunderstanding your point? – Beenish Khurshid Jun 08 '21 at 20:06
  • That question doesn't have a `const` member variable so the default constructor is not deleted - so, not the same thing. – Ted Lyngmo Jun 08 '21 at 20:11
  • Is there a specific paragraph in the standard document that you added a link to that you believe makes it clear that the default constructor shouldn't be deleted? [All four implementations](https://godbolt.org/z/9f4j7fehc) in the question deletes it - yet g++ and clang++ think it `is_trivial`. – Ted Lyngmo Jun 08 '21 at 20:42
  • 1
    Page 281 in the same document: "_A defaulted default constructor for class X is defined as deleted if: ... any non-variant non-static data member of const-qualified type (or array thereof) with no brace-orequal-initializer does not have a user-provided default constructor_" - and `const int` doesn't have a user-provided default constructor. So, the default constructor is defined - as deleted. – Ted Lyngmo Jun 08 '21 at 21:02
  • Interesting. I didn't catch that part. So maybe Clang and GCC are going more for the spirit rather than the letter seeing as the intent of POD seemed to have been to C compatible. – Beenish Khurshid Jun 08 '21 at 21:13
  • 1
    C doesn't have constructors and is a bit more relaxed. It's apparently fine to create an `A` with an uninitialized `const` member variable in C. I'm not sure what it'll be good for though. I _think_ it's UB to read uninitialized variables even in C. – Ted Lyngmo Jun 08 '21 at 21:24
  • 1
    @BeenishKhurshid [gcc](https://wandbox.org/permlink/kaoqt04Wv4ulMQeE) and [clang](https://wandbox.org/permlink/keNVqfIebU36sVCG) will both tell you that the default constructor is deleted. – Ryan Haining Jun 09 '21 at 16:48
  • @BeenishKhurshid The concept that a type is C compatible (i.e. *not considering construction or destruction* it is usable from both C and C++) is called "standard layout". It makes no sense for is_pod to use that criterion. If you want to know about this kind of C compatibility, is_standard_layout (also available since C++11) is the trait you should use. – Michael Karcher Jun 10 '21 at 05:59
  • For the record, someone put this response in the "low quality" queue. This may be the case (I mean: low quality). But the discussion under the answer is certainly NOT of poor quality. I voted "looks OK" because I don't have the skills to fix it. Do not suppress this kind of response! – manuell Jun 11 '21 at 17:15