| | 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 | } |