1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// This file does nothing functional!
// It test support for main C++11 features
// In the future, it might be extended to test also C++14, C++17, C++20 and any future standard
//
// In order to enable the tests, we have to `define ENABLE_TEST_CPP_11` (and of course, compile this file)
// Then it should print "Testing C++11" *during compilation*
// If the message is printed, and there are no compilation errors - great, C++11 is supported on this platform
// If there are errors, each one of the tests can be disabled, by defining the relevant DONT_TEST_*
// It's important to disable failing tests, because we might decide to support only specific subset of C++11
//
// Note: there are 3 warnings in my GCC run, they have no signficance
#if defined(NONSTANDARD_PORT)
#include "portdefs.h"
#endif
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#ifdef ENABLE_TEST_CPP_11
#pragma message("Testing C++11")
// The tests are based on https://blog.petrzemek.net/2014/12/07/improving-cpp98-code-with-cpp11/
// See there for further links and explanations
//
// We're not testing `nullptr` and `override`, since they're defined in common/c++11-compat.h
#include "common/array.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/rect.h"
#ifndef DONT_TEST_UNICODE_STRING_LITERAL
const char16_t *u16str = u"\u00DAnicode string";
const char32_t *u32str = U"\u00DAnicode string";
#endif
#ifndef DONT_TEST_INITIALIZIER_LIST1
#ifndef USE_INITIALIZIER_LIST_REPLACEMENT
#include <initializer_list>
#else
namespace std {
template<class T> class initializer_list {
public:
typedef T value_type;
typedef const T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef const T* iterator;
typedef const T* const_iterator;
constexpr initializer_list() noexcept = default;
constexpr size_t size() const noexcept { return m_size; };
constexpr const T* begin() const noexcept { return m_begin; };
constexpr const T* end() const noexcept { return m_begin + m_size; }
private:
// Note: begin has to be first or the compiler gets very upset
const T* m_begin = { nullptr };
size_t m_size = { 0 };
// The compiler is allowed to call this constructor
constexpr initializer_list(const T* t, size_t s) noexcept : m_begin(t) , m_size(s) {}
};
template<class T> constexpr const T* begin(initializer_list<T> il) noexcept {
return il.begin();
}
template<class T> constexpr const T* end(initializer_list<T> il) noexcept {
return il.end();
}
} // end namespace std
#endif
#endif
#ifndef DONT_TEST_CLASS_ENUM
// ----------------------------------
// Scoped/Strongly Typed Enumerations
// ----------------------------------
enum class MyEnum {
VAL1,
VAL2,
VAL3
};
#endif
#ifndef DONT_TEST_FINAL_CLASS
// ----------------------------------
// Non-Inheritable Classes (final)
// ----------------------------------
// C++11
class TestNewStandards final {
#else
class TestNewStandards {
#endif
private:
void do_nothing(const int &i) {
// don't do anything with i
};
#ifndef DONT_TEST_STRING_LITERAL_INIT
// ----------------------------------
// Char arrays initialized by a string literal
// * note - not properly implemented before GCC 5.1 (GCC Bug #43453)
// ----------------------------------
char _emptyMsg[1] = "";
#else
char _emptyMsg[1] = { '\0' };
#endif
#ifndef DONT_TEST_FINAL_FUNCTION
// ----------------------------------
// Non-Overridable Member Functions (final)
// ----------------------------------
virtual void f() final {}
#endif
#ifndef DONT_TEST_VARIADIC_TEMPLATES
// ------------------------
// Variadic Templates
// ------------------------
template <typename T>
void variadic_function(const T &value) {
do_nothing(value);
}
template <typename U, typename... T>
void variadic_function(const U &head, const T &... tail) {
do_nothing(head);
variadic_function(tail...);
}
#endif
#ifndef DONT_TEST_TYPE_ALIASES
// ------------------------
// Type Aliases
// * note - this test has another bunch of code below
// ------------------------
// C++98
template<typename T>
struct Dictionary_98 {
typedef Common::HashMap<Common::String, T, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> type;
};
// Usage:
Dictionary_98<int>::type d98;
// C++11
template <typename T>
using Dictionary_11 = Common::HashMap<Common::String, T, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>;
// Usage:
Dictionary_11<int> d11;
#endif
#ifndef DONT_TEST_INITIALIZIER_LIST1
// Array with C++11 initialization list
template<class T> class ArrayCpp11 : public Common::Array<T> {
public:
ArrayCpp11(std::initializer_list<T> list) {
if (list.size()) {
this->allocCapacity(list.size());
Common::uninitialized_copy(list.begin(), list.end(), this->_storage);
}
}
};
#endif
void test_cpp11() {
#ifdef DONT_TEST_INITIALIZIER_LIST1
// ------------------------
// Initializer list
// ------------------------
// C++98
Common::Array<int> arr;
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
#else
// C++11
ArrayCpp11<int> arr = {1, 2, 3};
#endif
#ifndef DONT_TEST_INITIALIZIER_LIST2
// C++11
Common::Point arr3[] = {{0, 0}, {1, 1}};
#endif
#ifndef DONT_TEST_AUTO_TYPE_INFERENCE
// ------------------------
// Automatic Type Inference
// ------------------------
// C++98
for (Common::Array<int>::iterator i = arr.begin(), e = arr.end(); i != e; ++i)
;
// C++11
for (auto i = arr.begin(), e = arr.end(); i != e; ++i)
;
#endif
#ifndef DONT_TEST_RANGE_BASED_FOR_LOOP
// ------------------------
// Range based for loop
// ------------------------
// C++98
for (Common::Array<int>::iterator i = arr.begin(), e = arr.end(); i != e; ++i)
do_nothing(*i);
// C++11
for (int &i : arr)
do_nothing(i);
#endif
#ifndef DONT_TEST_LAMBDA_FUNCTIONS
// ------------------------
// Lambda functions
// ------------------------
// C++98
// the following isn't working in VS, but it's not really important to debug...
// Common::for_each(arr.begin(), arr.end(), do_nothing);
// C++11
Common::for_each(arr.begin(), arr.end(),
[](int i) {
// don't do anything with i
}
);
#endif
#ifndef DONT_TEST_VARIADIC_TEMPLATES
variadic_function(1, 1, 2, 3, 5, 8, 13, 21, 34);
#endif
#ifndef DONT_TEST_GET_RID_OF_SPACE_IN_NESTED_TEMPLATES
// ------------------------
// No Need For an Extra Space In Nested Template Declarations
// ------------------------
// C++98
Common::Array<Common::Array<int> > v_98;
// C++11
Common::Array<Common::Array<int>> v_11;
#endif
#ifndef DONT_TEST_TYPE_ALIASES
// ------------------------
// Type Aliases
// * note - this test has another bunch of code above
// ------------------------
// C++98
typedef void (*fp_98)(int, int);
// C++11
using fp_11 = void (*)(int, int);
#endif
};
#ifndef DONT_TEST_ALT_FUNCTION_SYNTAX
// ------------------------
// Alternative Function Syntax
// ------------------------
// C++98
int f_98(int x, int y) {return x;}
// C++11
auto f_11(int x, int y) -> int {return x;}
#endif
#ifndef DONT_TEST_NON_STATIC_INIT
// ------------------------
// Non-Static Data Member Initializers
// ------------------------
int j = 3;
Common::String s = "non static init";
#endif
#ifndef DONT_TEST_EXPLICIT
// ------------------------
// Explicit Conversion Operators
// ------------------------
explicit operator bool() const {return true;}
#endif
public:
TestNewStandards() {
test_cpp11();
}
#ifndef DONT_TEST_MOVE_SEMANTICS
// ------------------------
// Move semantics
// Note: this test hasn't been taken from the aforementioned web page
// ------------------------
TestNewStandards(TestNewStandards&& t) {
// I'm not convinced that it's a good example of move sematics, it's a complicated topic. But just checking the syntax.
}
#endif
#ifndef DONT_TEST_DELETED_FUNCTIONS
// ------------------------
// Explicitly Deleted Functions
// (useful for non copyable classes,
// particularly for our Singleton class)
// ------------------------
TestNewStandards &operator=(const TestNewStandards &) = delete;
#endif
};
static TestNewStandards test = TestNewStandards();
#endif
|