#include <array>

char const * foo1(double const arg1[3]);
char const mypass_version[4] = "1.0";
int const volatile x = 0;

class A {
   
   
   public:
   void constFoo() const;
   static int constexpr number_of_sizes = 3;
   static std::array<int, number_of_sizes> constexpr SPACE{{512, 256, 128}};
   static std::array<int, number_of_sizes> constexpr SPACE2 = {512, 256, 128};
   static std::array<std::array<int, 2>, 1> constexpr ARRAY_IN_ARRAY{{{{1, 2}}}};
   static std::array<std::array<int, 2>, 1> constexpr ARRAY_IN_ARRAY2 = {{1, 2}};
};

inline void A::constFoo() const {
}

// constexpr static members need to be allocated outside os the class/structure
std::array<int, A::number_of_sizes> constexpr A::SPACE;
std::array<int, A::number_of_sizes> constexpr A::SPACE2;
std::array<std::array<int, 2>, 1> constexpr A::ARRAY_IN_ARRAY;
std::array<std::array<int, 2>, 1> constexpr A::ARRAY_IN_ARRAY2;

int main() {
   int n1 = 0; // non-const object
   static int const n2 = 0; // const object
   int const n3 = 0; // const object (same as n2)
   int volatile n4 = 0; // volatile object
   
   const struct {
      int n1;
      mutable int n2;
   } x = {0, 0};

   n1 = 1; // ok, modifiable object
   //  n2 = 2; // error: non-modifiable object
   n4 = 3; // ok, treated as a side-effect
   //  x.n1 = 4; // error: member of a const object is const
   x.n2 = 4; // ok, mutable member of a const object isn't const
   int const & r1 = n1; // reference to const bound to non-const object
   //  r1 = 2; // error: attempt to modify through reference to const
   const_cast<int &>(r1) = 2; // ok, modifies non-const object n1
   int const & r2 = n2; // reference to const bound to const object
   //  r2 = 2; // error: attempt to modify through reference to const
   //  const_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2
   // Taken from http://duramecho.com/ComputerInformation/WhyHowCppConst.html
   // variable pointer to a constant integer
   int const *constant1;
   int const *constant2;
   // constant pointer to a variable integer
   int * const constant3 = nullptr;
   // constant pointer to a constant integer
   int const * const constant4 = nullptr;
   
   const struct {
      int n1;
   } x2 = {0};
}
