| 1 | // Use, modification and distribution are subject to the |
| 2 | // Boost Software License, Version 1.0. (See accompanying file |
| 3 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 4 | |
| 5 | // See http://www.boost.org/libs/config for most recent version. |
| 6 | |
| 7 | // MACRO: BOOST_NO_COMPLETE_VALUE_INITIALIZATION |
| 8 | // TITLE: No complete value-initialization |
| 9 | // DESCRIPTION: This macro must be defined, if and only if the compiler |
| 10 | // does not to have implemented value-initialization completely. |
| 11 | // See also boost/libs/utility/value_init.htm#compiler_issues |
| 12 | |
| 13 | #include <boost/config.hpp> |
| 14 | #include <cstdlib> |
| 15 | #include <iostream> |
| 16 | |
| 17 | namespace |
| 18 | { |
| 19 | enum enum_type { negative_number = -1, magic_number = 42 }; |
| 20 | |
| 21 | // A POD struct. |
| 22 | struct pod_struct |
| 23 | { |
| 24 | enum_type e; |
| 25 | char c; |
| 26 | unsigned char uc; |
| 27 | short s; |
| 28 | int i; |
| 29 | unsigned u; |
| 30 | long l; |
| 31 | float f; |
| 32 | double d; |
| 33 | void* p; |
| 34 | }; |
| 35 | |
| 36 | bool is_zero_initialized(const pod_struct& arg) |
| 37 | { |
| 38 | return |
| 39 | arg.e == 0 && |
| 40 | arg.c == 0 && |
| 41 | arg.uc == 0 && |
| 42 | arg.s == 0 && |
| 43 | arg.i == 0 && |
| 44 | arg.u == 0 && |
| 45 | arg.l == 0 && |
| 46 | arg.f == 0 && |
| 47 | arg.d == 0 && |
| 48 | arg.p == 0; |
| 49 | } |
| 50 | |
| 51 | // A class that holds a "magic" enum value. |
| 52 | class enum_holder |
| 53 | { |
| 54 | enum_type m_enum; |
| 55 | public: |
| 56 | |
| 57 | enum_holder() |
| 58 | : |
| 59 | m_enum(magic_number) |
| 60 | { |
| 61 | } |
| 62 | |
| 63 | bool is_default() const |
| 64 | { |
| 65 | return m_enum == magic_number; |
| 66 | } |
| 67 | }; |
| 68 | |
| 69 | |
| 70 | // A class that is not a POD type. |
| 71 | class non_pod_class |
| 72 | { |
| 73 | private: |
| 74 | enum_holder m_enum_holder; |
| 75 | |
| 76 | public: |
| 77 | int i; |
| 78 | |
| 79 | virtual bool is_value_initialized() const |
| 80 | { |
| 81 | return m_enum_holder.is_default() && i == 0; |
| 82 | } |
| 83 | |
| 84 | virtual ~non_pod_class() {} |
| 85 | }; |
| 86 | |
| 87 | // The first argument (is_value_initializated) tells whether value initialization |
| 88 | // has succeeded. |
| 89 | // The second argument tells what expression was evaluated. |
| 90 | bool is_true(bool is_value_initializated, const char *const expression) |
| 91 | { |
| 92 | if ( ! is_value_initializated ) |
| 93 | { |
| 94 | #ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION |
| 95 | std::cout |
| 96 | << "Information: " << expression << " evaluated to false.\n" |
| 97 | << " Therefor BOOST_NO_COMPLETE_VALUE_INITIALIZATION is defined for this compiler." |
| 98 | << std::endl; |
| 99 | #else |
| 100 | std::cerr |
| 101 | << "Error: " << expression << " evaluated to false.\n" |
| 102 | << " Please consider defining BOOST_NO_COMPLETE_VALUE_INITIALIZATION for this compiler." |
| 103 | << std::endl; |
| 104 | #endif |
| 105 | } |
| 106 | return is_value_initializated; |
| 107 | } |
| 108 | |
| 109 | #define IS_TRUE(value) is_true(value, #value) |
| 110 | #define IS_ZERO(value) is_true(value == 0, #value " == 0") |
| 111 | |
| 112 | // The default constructor of this class initializes each of its |
| 113 | // data members by means of an empty set of parentheses, and checks |
| 114 | // whether each of them is value-initialized. |
| 115 | class value_initializer |
| 116 | { |
| 117 | private: |
| 118 | enum_holder m_enum_holder; |
| 119 | enum_type m_enum; |
| 120 | char m_char; |
| 121 | unsigned char m_unsigned_char; |
| 122 | short m_short; |
| 123 | int m_int; |
| 124 | unsigned m_unsigned; |
| 125 | long m_long; |
| 126 | float m_float; |
| 127 | double m_double; |
| 128 | void* m_ptr; |
| 129 | pod_struct m_pod; |
| 130 | pod_struct m_pod_array[2]; |
| 131 | non_pod_class m_non_pod; |
| 132 | non_pod_class m_non_pod_array[2]; |
| 133 | |
| 134 | public: |
| 135 | value_initializer() |
| 136 | : |
| 137 | m_enum_holder(), |
| 138 | m_enum(), |
| 139 | m_char(), |
| 140 | m_unsigned_char(), |
| 141 | m_short(), |
| 142 | m_int(), |
| 143 | m_unsigned(), |
| 144 | m_long(), |
| 145 | m_float(), |
| 146 | m_double(), |
| 147 | m_ptr(), |
| 148 | m_pod(), |
| 149 | m_pod_array(), |
| 150 | m_non_pod(), |
| 151 | m_non_pod_array() |
| 152 | { |
| 153 | } |
| 154 | |
| 155 | // Returns the number of failures. |
| 156 | unsigned check() const |
| 157 | { |
| 158 | return |
| 159 | (IS_TRUE( m_enum_holder.is_default() ) ? 0 : 1) + |
| 160 | (IS_ZERO(m_enum) ? 0 : 1) + |
| 161 | (IS_ZERO(m_char) ? 0 : 1) + |
| 162 | (IS_ZERO(m_unsigned_char) ? 0 : 1) + |
| 163 | (IS_ZERO(m_short) ? 0 : 1) + |
| 164 | (IS_ZERO(m_int) ? 0 : 1) + |
| 165 | (IS_ZERO(m_unsigned) ? 0 : 1) + |
| 166 | (IS_ZERO(m_long) ? 0 : 1) + |
| 167 | (IS_ZERO(m_float) ? 0 : 1) + |
| 168 | (IS_ZERO(m_double) ? 0 : 1) + |
| 169 | (IS_ZERO(m_ptr) ? 0 : 1) + |
| 170 | (IS_TRUE( is_zero_initialized(m_pod) ) ? 0 : 1) + |
| 171 | (IS_TRUE( m_non_pod.is_value_initialized() ) ? 0 : 1) + |
| 172 | (IS_TRUE( is_zero_initialized(m_pod_array[0]) |
| 173 | && is_zero_initialized(m_pod_array[1]) ) ? 0 : 1) + |
| 174 | (IS_TRUE( m_non_pod_array[0].is_value_initialized() |
| 175 | && m_non_pod_array[1].is_value_initialized() ) ? 0 : 1); |
| 176 | |
| 177 | } |
| 178 | }; |
| 179 | |
| 180 | } // End of namespace. |
| 181 | |
| 182 | int main(int, char*[]) |
| 183 | { |
| 184 | // Check both value-initialization on the stack and on the heap: |
| 185 | const unsigned num_failures_on_stack = value_initializer().check(); |
| 186 | const value_initializer* const ptr = new value_initializer(); |
| 187 | const unsigned num_failures_on_heap = ptr->check(); |
| 188 | delete ptr; |
| 189 | |
| 190 | const bool completely_value_initialized = |
| 191 | num_failures_on_stack == 0 && num_failures_on_heap == 0; |
| 192 | |
| 193 | #ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION |
| 194 | return completely_value_initialized ? EXIT_FAILURE : EXIT_SUCCESS; |
| 195 | #else |
| 196 | return completely_value_initialized ? EXIT_SUCCESS : EXIT_FAILURE; |
| 197 | #endif |
| 198 | } |