Rule A11-0-1 (advisory, implementation, automated)

A non-POD type should be defined as class.

Rationale

Types that are not POD types are supposed to be defined as class objects, as a class specifier forces the type to provide private access control for all its members by default. This is consistent with developer expectations, because it is expected that a class has its invariant, interface and could provide custom-defined constructors.

Example

// $Id: A11-0-1.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $ #include <cstdint> #include <limits> class A // Compliant - A provides user-defined constructors, invariant and // interface { std::int32_t x; // Data member is private by default public: static constexpr std::int32_t maxValue = std::numeric_limits<std::int32_t>::max(); A() : x(maxValue) {} explicit A(std::int32_t number) : x(number) {} A(A const&) = default; A(A&&) = default; A& operator=(A const&) = default; A& operator=(A&&) = default; std::int32_t GetX() const noexcept { return x; } void SetX(std::int32_t number) noexcept { x = number; } }; struct B // Non-compliant - non-POD type defined as struct { public: static constexpr std::int32_t maxValue = std::numeric_limits<std::int32_t>::max(); B() : x(maxValue) {} explicit B(std::int32_t number) : x(number) {} B(B const&) = default; B(B&&) = default; B& operator=(B const&) = default; B& operator=(B&&) = default; std::int32_t GetX() const noexcept { return x; } void SetX(std::int32_t number) noexcept { x = number; } private: std::int32_t x; // Need to provide private access specifier for x member }; struct C // Compliant - POD type defined as struct { std::int32_t x; std::int32_t y; }; class D // Compliant - POD type defined as class, but not compliant with // M11-0-1 { public: std::int32_t x; std::int32_t y; };

See also

C++ Core Guidelines [11]: C.2: Use class if the class has an invariant; use struct if the data members can vary independently. stackoverflow.com [17]: When should you use a class vs a struct in C++?