From 7d07140cd1a93feb3ad571f09515ed8e7c2ae5fc Mon Sep 17 00:00:00 2001 From: "Marcus R. Brown" Date: Mon, 21 Sep 2015 10:30:03 -0700 Subject: [PATCH 01/59] Fix the broken isocpp.org link in README.md. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44d05e4..4678637 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # GSL: Guidelines Support Library The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the -[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](isocpp.org). +[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). This repo contains Microsoft's implementation of GSL, tracking Microsoft's fork of the Guidelines. Microsoft's fork can be found here: -[C++ Core Guidelines](https://github.com/Microsoft/CppCoreGuidelines). +[C++ Core Guidelines](https://github.com/Microsoft/CppCoreGuidelines). The library includes types like `array_view<>`, `string_view<>`, `owner<>` and others. From 5d9aae7430ed15cc573b901b665dea5703a0cdeb Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 21 Sep 2015 16:04:06 -0300 Subject: [PATCH 02/59] Add add_gsl_test() function in tests/CMakeLists.txt With this function we can avoid duplicated code to add a new test. --- tests/CMakeLists.txt | 144 ++++++------------------------------------- 1 file changed, 20 insertions(+), 124 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index afe24a3..ad7a38c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,128 +31,24 @@ if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/unittest-cpp) message(FATAL_ERROR "Could not find unittest-cpp enlistment. Please run 'git clone https://github.com/Microsoft/unittest-cpp.git unittest-cpp' in the tests directory") endif() -add_executable(array_view_tests - array_view_tests.cpp -) -target_link_libraries(array_view_tests - UnitTest++ -) -install(TARGETS array_view_tests - RUNTIME DESTINATION bin -) -add_test( - NAME array_view_tests - COMMAND array_view_tests -) +function(add_gsl_test name) + add_executable(${name} ${name}.cpp) + target_link_libraries(${name} UnitTest++) + install(TARGETS ${name} + RUNTIME DESTINATION bin + ) + add_test( + NAME ${name} + COMMAND ${name} + ) +endfunction() -add_executable(string_view_tests - string_view_tests.cpp -) -target_link_libraries(string_view_tests - UnitTest++ -) -install(TARGETS string_view_tests - RUNTIME DESTINATION bin -) -add_test( - NAME string_view_tests - COMMAND string_view_tests -) - -add_executable(at_tests - at_tests.cpp -) -target_link_libraries(at_tests - UnitTest++ -) -install(TARGETS at_tests - RUNTIME DESTINATION bin -) -add_test( - NAME at_tests - COMMAND at_tests -) - -add_executable(bounds_tests - bounds_tests.cpp -) -target_link_libraries(bounds_tests - UnitTest++ -) -install(TARGETS bounds_tests - RUNTIME DESTINATION bin -) -add_test( - NAME bounds_tests - COMMAND bounds_tests -) - -add_executable(maybenull_tests - maybenull_tests.cpp -) -target_link_libraries(maybenull_tests - UnitTest++ -) -install(TARGETS maybenull_tests - RUNTIME DESTINATION bin -) -add_test( - NAME maybenull_tests - COMMAND maybenull_tests -) - -add_executable(notnull_tests - notnull_tests.cpp -) -target_link_libraries(notnull_tests - UnitTest++ -) -install(TARGETS notnull_tests - RUNTIME DESTINATION bin -) -add_test( - NAME notnull_tests - COMMAND notnull_tests -) - -add_executable(assertion_tests - assertion_tests.cpp -) -target_link_libraries(assertion_tests - UnitTest++ -) -install(TARGETS assertion_tests - RUNTIME DESTINATION bin -) -add_test( - NAME assertion_tests - COMMAND assertion_tests -) - -add_executable(utils_tests - utils_tests.cpp -) -target_link_libraries(utils_tests - UnitTest++ -) -install(TARGETS utils_tests - RUNTIME DESTINATION bin -) -add_test( - NAME utils_tests - COMMAND utils_tests -) - -add_executable(owner_tests - owner_tests.cpp -) -target_link_libraries(owner_tests - UnitTest++ -) -install(TARGETS owner_tests - RUNTIME DESTINATION bin -) -add_test( - NAME owner_tests - COMMAND owner_tests -) +add_gsl_test(array_view_tests) +add_gsl_test(string_view_tests) +add_gsl_test(at_tests) +add_gsl_test(bounds_tests) +add_gsl_test(maybenull_tests) +add_gsl_test(notnull_tests) +add_gsl_test(assertion_tests) +add_gsl_test(utils_tests) +add_gsl_test(owner_tests) From cb068d80cdbafa7a3b9e33bdf41a266a1c3d08bc Mon Sep 17 00:00:00 2001 From: galik Date: Mon, 21 Sep 2015 22:51:46 +0100 Subject: [PATCH 03/59] missing header --- include/fail_fast.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fail_fast.h b/include/fail_fast.h index 382b9d6..dfd0ede 100644 --- a/include/fail_fast.h +++ b/include/fail_fast.h @@ -17,6 +17,7 @@ #pragma once #include +#include namespace Guide { From e7c0b89ed4a730c43376f5c4af43ec5159879ac9 Mon Sep 17 00:00:00 2001 From: Andrew Pardoe Date: Mon, 21 Sep 2015 19:58:25 -0700 Subject: [PATCH 04/59] Removed reference to Microsoft private fork --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 4678637..e34948a 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). -This repo contains Microsoft's implementation of GSL, tracking Microsoft's fork of the Guidelines. Microsoft's fork can be found here: -[C++ Core Guidelines](https://github.com/Microsoft/CppCoreGuidelines). +This repo contains Microsoft's implementation of GSL. The library includes types like `array_view<>`, `string_view<>`, `owner<>` and others. From 1228e17762648fc19cb989b3c2d47f440089d101 Mon Sep 17 00:00:00 2001 From: Rico Antonio Felix Date: Tue, 22 Sep 2015 13:38:47 -0400 Subject: [PATCH 05/59] Corrected grammatical error... --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ce68e8..990b8e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ The Guidelines Support Library (GSL) contains functions and types that are sugge [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines). GSL design changes are made only as a result of modifications to the Guidelines. GSL is accepting contributions that improve or refine any of the types in this library as well as ports to other platforms. Changes should have an issue -tracking the suggestion that has been approved the maintainers. Your pull request should include a link to the bug that you are fixing. If you've submitted +tracking the suggestion that has been approved by the maintainers. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR, please post a comment in the associated issue to avoid duplication of effort. ## Legal From 9b454b7a9bc2ff2c608dcb66c4dfccdc1c40e150 Mon Sep 17 00:00:00 2001 From: Tamas Kenez Date: Wed, 23 Sep 2015 17:43:36 +0200 Subject: [PATCH 06/59] add travis testing (gcc5, clang36) - also relaxed CMake version to 2.8.7, the version default in travis --- .travis.yml | 67 ++++++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 6 ++-- README.md | 18 ++++++------ tests/CMakeLists.txt | 10 +++---- 4 files changed, 84 insertions(+), 17 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..524f1fb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,67 @@ +# Based on https://github.com/ldionne/hana/blob/master/.travis.yml + +language: cpp +sudo: false + +matrix: + include: + - env: COMPILER=clang++-3.6 BUILD_TYPE=Debug CLANG=1 + compiler: clang + addons: &clang36 + apt: + packages: + - clang-3.6 + - cmake + sources: &sources + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 + - kalakris-cmake + - env: COMPILER=clang++-3.6 BUILD_TYPE=Release CLANG=1 + compiler: clang + addons: *clang36 + - env: COMPILER=g++-5 BUILD_TYPE=Debug + compiler: gcc + addons: &gcc5 + apt: + packages: g++-5 + sources: *sources + - env: COMPILER=g++-5 BUILD_TYPE=Release + compiler: gcc + addons: *gcc5 + +install: + - which $COMPILER + - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" + - mkdir ${DEPS_DIR} && cd ${DEPS_DIR} + - | + if [[ "$CLANG" == 1 && "${TRAVIS_OS_NAME}" == "linux" && "${STDLIB}" != "libstdc++" ]]; then + if [[ "${COMPILER}" == "clang++-3.5" ]]; then LLVM_VERSION="3.5.2"; fi + if [[ "${COMPILER}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2"; fi + if [[ "${COMPILER}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.0"; fi + LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz" + LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz" + LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz" + mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi + travis_retry wget --quiet -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm + travis_retry wget --quiet -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx + travis_retry wget --quiet -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi + (cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${DEPS_DIR}/llvm/install -DCMAKE_CXX_COMPILER=clang++) + (cd llvm/build/projects/libcxx && make install -j2) + (cd llvm/build/projects/libcxxabi && make install -j2) + export CXXFLAGS="-I ${DEPS_DIR}/llvm/install/include/c++/v1" + export LDFLAGS="-L ${DEPS_DIR}/llvm/install/lib -l c++ -l c++abi" + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${DEPS_DIR}/llvm/install/lib" + fi + +before_script: + - cd ${TRAVIS_BUILD_DIR} + - git clone --depth 1 https://github.com/Microsoft/unittest-cpp tests/unittest-cpp + - cmake -H. -Bb -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_INSTALL_PREFIX=$PWD/o -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - cmake --build b + +script: + - cd b + - ctest + +notifications: + email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 2125f7b..f8145d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ -cmake_minimum_required(VERSION 3.2.2) +cmake_minimum_required(VERSION 2.8.7) -project(GSL) +project(GSL CXX) include_directories( ${CMAKE_CURRENT_BINARY_DIR} @@ -8,4 +8,4 @@ include_directories( enable_testing() -add_subdirectory(tests) \ No newline at end of file +add_subdirectory(tests) diff --git a/README.md b/README.md index e34948a..300b103 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# GSL: Guidelines Support Library +# GSL: Guidelines Support Library [![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL) The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the -[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). +[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). This repo contains Microsoft's implementation of GSL. The library includes types like `array_view<>`, `string_view<>`, `owner<>` and others. @@ -12,7 +12,7 @@ While some types have been broken out into their own headers (e.g. [include/arra it is simplest to just include [gsl.h](./include/gsl.h) and gain access to the entire library. > NOTE: We encourage contributions that improve or refine any of the types in this library as well as ports to -other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more information about contributing. +other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more information about contributing. # Quick Start ## Supported Platforms @@ -27,13 +27,13 @@ The test suite that exercises GSL has been built and passes successfully on the * Mac OS Yosemite using XCode with AppleClang 7.0.0.7000072 * Mac OS Yosemite using GCC-5.2.0 -> If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider -contributing any changes that were necessary back to this project to benefit the wider community. +> If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider +contributing any changes that were necessary back to this project to benefit the wider community. ## Building the tests To build the tests, you will require the following: -* [CMake](http://cmake.org), version 3.3 or later to be installed and in your PATH. +* [CMake](http://cmake.org), version 2.8.7 or later to be installed and in your PATH. * [UnitTest-cpp](https://github.com/Microsoft/unittest-cpp), to be cloned under the [tests/unittest-cpp](./tests/unittest-cpp) directory of your GSL source. @@ -46,13 +46,13 @@ These steps assume the source code of this repository has been cloned into a dir cd build-x86 2. Configure CMake to use the compiler of your choice (you can see a list by running `cmake --help`). - + cmake -G "Visual Studio 14 2015" c:\GSL - + 3. Build the test suite (in this case, in the Debug configuration, Release is another good choice). cmake --build . --config Debug - + 4. Run the test suite. ctest -C Debug diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ad7a38c..0415db3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ -cmake_minimum_required(VERSION 3.2.2) +cmake_minimum_required(VERSION 2.8.7) -project(GSLTests) +project(GSLTests CXX) add_subdirectory(unittest-cpp) @@ -23,7 +23,7 @@ else() elseif(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() endif() @@ -38,8 +38,8 @@ function(add_gsl_test name) RUNTIME DESTINATION bin ) add_test( - NAME ${name} - COMMAND ${name} + ${name} + ${name} ) endfunction() From c3b85f9571d43b8330dba8d08cc8a8e85af67059 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 23 Sep 2015 22:12:49 +0200 Subject: [PATCH 07/59] Fixes spelling of Xcode --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e34948a..c169d19 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The test suite that exercises GSL has been built and passes successfully on the * Windows using GCC 5.1 * GNU/Linux using Clang/LLVM 3.6 * GNU/Linux using GCC 5.1 -* Mac OS Yosemite using XCode with AppleClang 7.0.0.7000072 +* Mac OS Yosemite using Xcode with AppleClang 7.0.0.7000072 * Mac OS Yosemite using GCC-5.2.0 > If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider From 2c8886bdfb532702484ee0c8d28c5b483c34fb6f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 23 Sep 2015 23:18:48 +0200 Subject: [PATCH 08/59] Also renames MAC OS to OS X --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c169d19..506110f 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ The test suite that exercises GSL has been built and passes successfully on the * Windows using GCC 5.1 * GNU/Linux using Clang/LLVM 3.6 * GNU/Linux using GCC 5.1 -* Mac OS Yosemite using Xcode with AppleClang 7.0.0.7000072 -* Mac OS Yosemite using GCC-5.2.0 +* OS X Yosemite using Xcode with AppleClang 7.0.0.7000072 +* OS X Yosemite using GCC-5.2.0 > If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider contributing any changes that were necessary back to this project to benefit the wider community. From 996aa06e08163aa8a53105921702c09d55d20dec Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Thu, 24 Sep 2015 14:09:40 -0700 Subject: [PATCH 09/59] Fix issue #45: comparing two maybe_null_dbg's can cause fail_fast --- include/gsl.h | 2 ++ tests/maybenull_tests.cpp | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/include/gsl.h b/include/gsl.h index cf6eca5..1357d76 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -202,6 +202,8 @@ public: bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; } bool operator!=(const T& rhs) const { return !(*this == rhs); } + bool operator==(const maybe_null_dbg& rhs) const { tested_ = true; rhs.tested_ = true; return ptr_ == rhs.ptr_; } + bool operator!=(const maybe_null_dbg& rhs) const { return !(*this == rhs); } T get() const { fail_fast_assert(tested_); diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 1fdfb78..0a9d891 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -189,6 +189,58 @@ SUITE(MaybeNullTests) CHECK(q.present()); CHECK(q->foo()); } + + TEST(TestMaybeNullCompare) + { + int i1 = 1; + int i2 = 2; + + maybe_null_dbg p1 = &i1; + maybe_null_dbg p1_2 = &i1; + maybe_null_dbg p2 = &i2; + + CHECK_THROW(p1.get(), fail_fast); + CHECK_THROW(p1_2.get(), fail_fast); + CHECK_THROW(p2.get(), fail_fast); + + CHECK(p1 != p2); + CHECK(!(p1 == p2)); + CHECK(p1 == p1); + CHECK(p1 == p1_2); + + // Make sure we no longer throw here + CHECK(p1.get() != nullptr); + CHECK(p1_2.get() != nullptr); + CHECK(p2.get() != nullptr); + } + + TEST(TestMaybeNullCopy) + { + int i1 = 1; + int i2 = 2; + + maybe_null_dbg p1 = &i1; + maybe_null_dbg p1_2 = &i1; + maybe_null_dbg p2 = &i2; + + CHECK(p1 != p2); + CHECK(p1 == p1_2); + + // Make sure we no longer throw here + CHECK(p1.get() != nullptr); + CHECK(p2.get() != nullptr); + + p1 = p2; + + // Make sure we now throw + CHECK_THROW(p1.get(), fail_fast); + + CHECK(p1 == p2); + CHECK(p1 != p1_2); + + // Make sure we no longer throw here + CHECK(p1.get() != nullptr); + } } int main(int, const char *[]) From 35fb11853ff06d07805b121d928a1ba270532d1a Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Thu, 24 Sep 2015 18:02:37 -0700 Subject: [PATCH 10/59] Fix issues #48 #49 #50 --- include/gsl.h | 15 ++++++++++----- tests/maybenull_tests.cpp | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 1357d76..b78c6e2 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -162,7 +162,11 @@ private: template class maybe_null_dbg { + template + friend class maybe_null_dbg; public: + static_assert(std::is_constructible::value, "maybe_null's template parameter must be constructible from nullptr"); + maybe_null_dbg() : ptr_(nullptr), tested_(false) {} maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {} @@ -202,8 +206,10 @@ public: bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; } bool operator!=(const T& rhs) const { return !(*this == rhs); } - bool operator==(const maybe_null_dbg& rhs) const { tested_ = true; rhs.tested_ = true; return ptr_ == rhs.ptr_; } - bool operator!=(const maybe_null_dbg& rhs) const { return !(*this == rhs); } + template ::value>> + bool operator==(const maybe_null_dbg& rhs) const { tested_ = true; rhs.tested_ = true; return ptr_ == rhs.ptr_; } + template ::value>> + bool operator!=(const maybe_null_dbg& rhs) const { return !(*this == rhs); } T get() const { fail_fast_assert(tested_); @@ -217,8 +223,6 @@ public: T operator->() const { return get(); } private: - const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type - // unwanted operators...pointers only point to single objects! // TODO ensure all arithmetic ops on this type are unavailable maybe_null_dbg& operator++() = delete; @@ -238,6 +242,8 @@ template class maybe_null_ret { public: + static_assert(std::is_constructible::value, "maybe_null's template parameter must be constructible from nullptr"); + maybe_null_ret() : ptr_(nullptr) {} maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} maybe_null_ret(const T& p) : ptr_(p) {} @@ -280,7 +286,6 @@ private: maybe_null_ret& operator-(size_t) = delete; maybe_null_ret& operator-=(size_t) = delete; - const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type T ptr_; }; diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 0a9d891..e1244fd 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -241,6 +241,20 @@ SUITE(MaybeNullTests) // Make sure we no longer throw here CHECK(p1.get() != nullptr); } + + TEST(TestMaybeNullPtrT) + { + maybe_null p1; + maybe_null p2; + + CHECK_THROW(p1.get(), fail_fast); + + CHECK(p1 == p2); + + // Make sure we no longer throw here + CHECK(p1.get() == nullptr); + CHECK(p2.get() == nullptr); + } } int main(int, const char *[]) From 51da13607c655e8b57e82d1243b9283421182c27 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Thu, 24 Sep 2015 18:08:34 -0700 Subject: [PATCH 11/59] Fix issue #39: Add header guards --- include/array_view.h | 5 +++++ include/fail_fast.h | 5 +++++ include/gsl.h | 5 +++++ include/string_view.h | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/include/array_view.h b/include/array_view.h index 006f18c..26a1641 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_ARRAY_VIEW_H +#define GSL_ARRAY_VIEW_H + #include #include #include @@ -2286,3 +2289,5 @@ general_array_view_iterator operator+(typename general_array_view_ite #endif // _MSC_VER <= 1800 #pragma pop_macro("_NOEXCEPT") + +#endif // GSL_ARRAY_VIEW_H diff --git a/include/fail_fast.h b/include/fail_fast.h index dfd0ede..78a5102 100644 --- a/include/fail_fast.h +++ b/include/fail_fast.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_FAIL_FAST_H +#define GSL_FAIL_FAST_H + #include #include @@ -45,3 +48,5 @@ inline void fail_fast_assert(bool cond, const char* const) { if (!cond) std::ter #endif // SAFER_CPP_TESTING } + +#endif // GSL_FAIL_FAST_H diff --git a/include/gsl.h b/include/gsl.h index 1357d76..09a46c7 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_GSL_H +#define GSL_GSL_H + #include "array_view.h" // array_view, strided_array_view... #include "string_view.h" // zstring, string_view, zstring_builder... #include @@ -287,3 +290,5 @@ private: template using maybe_null = maybe_null_ret; } // namespace Guide + +#endif // GSL_GSL_H diff --git a/include/string_view.h b/include/string_view.h index 7becc8e..e683c7a 100644 --- a/include/string_view.h +++ b/include/string_view.h @@ -16,6 +16,9 @@ #pragma once +#ifndef GSL_STRING_VIEW_H +#define GSL_STRING_VIEW_H + #include "array_view.h" #include @@ -176,3 +179,5 @@ using zstring_builder = basic_zstring_builder; template using wzstring_builder = basic_zstring_builder; } + +#endif // GSL_STRING_VIEW_H From e1570268077b2b063f7397a804fe17690b2ddc9e Mon Sep 17 00:00:00 2001 From: Kern Handa Date: Fri, 25 Sep 2015 00:42:38 -0700 Subject: [PATCH 12/59] Rank and dimensions should be size_t. --- include/array_view.h | 132 +++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 006f18c..f9eadc4 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -71,20 +71,20 @@ namespace details }; - template + template class coordinate_facade { static_assert(std::is_integral::value && sizeof(ValueType) <= sizeof(size_t), "ValueType must be unsigned integral type!"); static_assert(Rank > 0, "Rank must be greater than 0!"); - template + template friend class coordinate_facade; public: using reference = ValueType&; using const_reference = const ValueType&; using value_type = ValueType; - static const unsigned int rank = Rank; + static const size_t rank = Rank; _CONSTEXPR coordinate_facade() _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); @@ -92,7 +92,7 @@ namespace details _CONSTEXPR coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] = values[i]; } _CONSTEXPR coordinate_facade(value_type e0) _NOEXCEPT @@ -106,7 +106,7 @@ namespace details { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); fail_fast_assert(il.size() == rank, "The size of the initializer list must match the rank of the array"); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { elems[i] = begin(il)[i]; } @@ -117,7 +117,7 @@ namespace details template _CONSTEXPR coordinate_facade(const coordinate_facade & other) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { fail_fast_assert(static_cast(other.elems[i]) <= SizeTypeTraits::max_value); elems[i] = static_cast(other.elems[i]); @@ -126,20 +126,20 @@ namespace details protected: coordinate_facade& operator=(const coordinate_facade& rhs) = default; // Preconditions: component_idx < rank - _CONSTEXPR reference operator[](unsigned int component_idx) + _CONSTEXPR reference operator[](size_t component_idx) { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } // Preconditions: component_idx < rank - _CONSTEXPR const_reference operator[](unsigned int component_idx) const + _CONSTEXPR const_reference operator[](size_t component_idx) const { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } _CONSTEXPR bool operator==(const ConcreteType& rhs) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (elems[i] != rhs.elems[i]) return false; @@ -157,7 +157,7 @@ namespace details _CONSTEXPR ConcreteType operator-() const { ConcreteType ret = to_concrete(); - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret.elems[i] = -ret.elems[i]; return ret; } @@ -175,13 +175,13 @@ namespace details } _CONSTEXPR ConcreteType& operator+=(const ConcreteType& rhs) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] += rhs.elems[i]; return to_concrete(); } _CONSTEXPR ConcreteType& operator-=(const ConcreteType& rhs) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] -= rhs.elems[i]; return to_concrete(); } @@ -229,13 +229,13 @@ namespace details } _CONSTEXPR ConcreteType& operator*=(value_type v) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] *= v; return to_concrete(); } _CONSTEXPR ConcreteType& operator/=(value_type v) { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) elems[i] /= v; return to_concrete(); } @@ -270,12 +270,12 @@ namespace details }; } -template +template class index : private details::coordinate_facade, ValueType, Rank> { using Base = details::coordinate_facade, ValueType, Rank>; friend Base; - template + template friend class index; public: using Base::rank; @@ -317,10 +317,10 @@ public: template class index<1, ValueType> { - template + template friend class index; public: - static const unsigned int rank = 1; + static const size_t rank = 1; using reference = ValueType&; using const_reference = const ValueType&; using size_type = ValueType; @@ -537,8 +537,8 @@ namespace details template struct BoundsRanges { - static const unsigned int Depth = 0; - static const unsigned int DynamicNum = 0; + static const size_t Depth = 0; + static const size_t DynamicNum = 0; static const SizeType CurrentRange = 1; static const SizeType TotalSize = 1; @@ -551,14 +551,14 @@ namespace details BoundsRanges() = default; - template + template void serialize(T &) const { } - template + template SizeType linearize(const T &) const { return 0; } - template + template ptrdiff_t contains(const T &) const { return 0; } @@ -576,8 +576,8 @@ namespace details template struct BoundsRanges : BoundsRanges{ using Base = BoundsRanges ; - static const unsigned int Depth = Base::Depth + 1; - static const unsigned int DynamicNum = Base::DynamicNum + 1; + static const size_t Depth = Base::Depth + 1; + static const size_t DynamicNum = Base::DynamicNum + 1; static const SizeType CurrentRange = dynamic_range; static const SizeType TotalSize = dynamic_range; const SizeType m_bound; @@ -596,19 +596,19 @@ namespace details { } - template + template void serialize(T & arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); } - template + template SizeType linearize(const T & arr) const { const size_t index = this->Base::totalSize() * arr[Dim]; fail_fast_assert(index < static_cast(m_bound)); return static_cast(index) + this->Base::template linearize(arr); } - template + template ptrdiff_t contains(const T & arr) const { const ptrdiff_t last = this->Base::template contains(arr); if (last == -1) @@ -625,7 +625,7 @@ namespace details return static_cast(totalSize() / this->Base::totalSize()); } - SizeType elementNum(unsigned int dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const _NOEXCEPT{ if (dim > 0) return this->Base::elementNum(dim - 1); else @@ -641,8 +641,8 @@ namespace details template struct BoundsRanges : BoundsRanges{ using Base = BoundsRanges ; - static const unsigned int Depth = Base::Depth + 1; - static const unsigned int DynamicNum = Base::DynamicNum; + static const size_t Depth = Base::Depth + 1; + static const size_t DynamicNum = Base::DynamicNum; static const SizeType CurrentRange = static_cast(CurRange); static const SizeType TotalSize = StaticSizeHelper::value; static_assert (CurRange <= SizeTypeTraits::max_value, "CurRange must be smaller than SizeType limits"); @@ -657,19 +657,19 @@ namespace details fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize()); } - template + template void serialize(T & arr) const { arr[Dim] = elementNum(); this->Base::template serialize(arr); } - template + template SizeType linearize(const T & arr) const { fail_fast_assert(arr[Dim] < CurrentRange, "Index is out of range"); return static_cast(this->Base::totalSize()) * arr[Dim] + this->Base::template linearize(arr); } - template + template ptrdiff_t contains(const T & arr) const { if (static_cast(arr[Dim]) >= CurrentRange) return -1; @@ -687,7 +687,7 @@ namespace details return CurrentRange; } - SizeType elementNum(unsigned int dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const _NOEXCEPT{ if (dim > 0) return this->Base::elementNum(dim - 1); else @@ -732,17 +732,17 @@ namespace details { const TypeChain & obj; TypeListIndexer(const TypeChain & obj) :obj(obj){} - template + template const TypeChain & getObj(std::true_type) { return obj; } - template + template auto getObj(std::false_type) -> decltype(TypeListIndexer(static_cast(obj)).template get()) { return TypeListIndexer(static_cast(obj)).template get(); } - template + template auto get() -> decltype(getObj(std::integral_constant())) { return getObj(std::integral_constant()); @@ -779,8 +779,8 @@ class static_bounds template friend class static_bounds; public: - static const unsigned int rank = MyRanges::Depth; - static const unsigned int dynamic_rank = MyRanges::DynamicNum; + static const size_t rank = MyRanges::Depth; + static const size_t dynamic_rank = MyRanges::DynamicNum; static const SizeType static_size = static_cast(MyRanges::TotalSize); using size_type = SizeType; @@ -844,12 +844,12 @@ public: return m_ranges.contains(idx) != -1; } - _CONSTEXPR size_type operator[](unsigned int index) const _NOEXCEPT + _CONSTEXPR size_type operator[](size_t index) const _NOEXCEPT { return m_ranges.elementNum(index); } - template + template _CONSTEXPR size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); @@ -888,12 +888,12 @@ public: } }; -template +template class strided_bounds : private details::coordinate_facade, SizeType, Rank> { using Base = details::coordinate_facade, SizeType, Rank>; friend Base; - template + template friend class strided_bounds; public: @@ -921,7 +921,7 @@ public: _CONSTEXPR strided_bounds(const index_type &extents, const index_type &strides) : m_strides(strides) { - for (unsigned int i = 0; i < rank; i++) + for (size_t i = 0; i < rank; i++) Base::elems[i] = extents[i]; } _CONSTEXPR strided_bounds(const value_type(&values)[rank], index_type strides) @@ -935,20 +935,20 @@ public: _CONSTEXPR size_type total_size() const _NOEXCEPT { size_type ret = 0; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret += (Base::elems[i] - 1) * m_strides[i]; return ret + 1; } _CONSTEXPR size_type size() const _NOEXCEPT { size_type ret = 1; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) ret *= Base::elems[i]; return ret; } _CONSTEXPR bool contains(const index_type& idx) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (idx[i] < 0 || idx[i] >= Base::elems[i]) return false; @@ -958,7 +958,7 @@ public: _CONSTEXPR size_type linearize(const index_type & idx) const { size_type ret = 0; - for (unsigned int i = 0; i < rank; i++) + for (size_t i = 0; i < rank; i++) { fail_fast_assert(idx[i] < Base::elems[i], "index is out of bounds of the array"); ret += idx[i] * m_strides[i]; @@ -974,7 +974,7 @@ public: { return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; } - template + template _CONSTEXPR size_type extent() const _NOEXCEPT { static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); @@ -1000,7 +1000,7 @@ template struct is_bounds : std::integral_constant {}; template struct is_bounds> : std::integral_constant {}; -template +template struct is_bounds> : std::integral_constant {}; template @@ -1014,7 +1014,7 @@ class bounds_iterator private: using Base = std::iterator , const IndexType>; public: - static const unsigned int rank = IndexType::rank; + static const size_t rank = IndexType::rank; using typename Base::reference; using typename Base::pointer; using typename Base::difference_type; @@ -1038,7 +1038,7 @@ public: } bounds_iterator& operator++() _NOEXCEPT { - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { if (++curr[i] < boundary[i]) { @@ -1050,7 +1050,7 @@ public: } } // If we're here we've wrapped over - set to past-the-end. - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { curr[i] = boundary[i]; } @@ -1096,11 +1096,11 @@ public: auto linear_idx = linearize(curr) + n; value_type stride; stride[rank - 1] = 1; - for (unsigned int i = rank - 1; i-- > 0;) + for (size_t i = rank - 1; i-- > 0;) { stride[i] = stride[i + 1] * boundary[i + 1]; } - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { curr[i] = linear_idx / stride[i]; linear_idx = linear_idx % stride[i]; @@ -1134,7 +1134,7 @@ public: } bool operator<(const bounds_iterator& rhs) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (curr[i] < rhs.curr[i]) return true; @@ -1164,7 +1164,7 @@ private: // TODO: Smarter impl. // Check if past-the-end bool pte = true; - for (unsigned int i = 0; i < rank; ++i) + for (size_t i = 0; i < rank; ++i) { if (idx[i] != boundary[i]) { @@ -1177,7 +1177,7 @@ private: if (pte) { res = 1; - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { res += (idx[i] - 1) * multiplier; multiplier *= boundary[i]; @@ -1185,7 +1185,7 @@ private: } else { - for (unsigned int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { res += idx[i] * multiplier; multiplier *= boundary[i]; @@ -1359,7 +1359,7 @@ template class basic_array_view { public: - static const unsigned int rank = BoundsType::rank; + static const size_t rank = BoundsType::rank; using bounds_type = BoundsType; using size_type = typename bounds_type::size_type; using index_type = typename bounds_type::index_type; @@ -1381,7 +1381,7 @@ public: { return m_bounds; } - template + template _CONSTEXPR size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); @@ -1537,7 +1537,7 @@ struct dim template class array_view; -template +template class strided_array_view; namespace details @@ -1616,7 +1616,7 @@ namespace details template struct is_array_view_oracle> : std::true_type {}; - template + template struct is_array_view_oracle> : std::true_type {}; template @@ -1930,12 +1930,12 @@ template _CONSTEXPR auto as_array_view(Cont &&arr) -> std::enable_if_t>::value, array_view, dynamic_range>> = delete; -template +template class strided_array_view : public basic_array_view::value_type, strided_bounds::size_type>> { using Base = basic_array_view::value_type, strided_bounds::size_type>>; - template + template friend class strided_array_view; public: using Base::rank; From 1a791992a0bc4b86bedd55768da9585ad9c08e70 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Fri, 25 Sep 2015 12:16:39 -0700 Subject: [PATCH 13/59] Add equality operators to maybe_nul_ret --- include/gsl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/gsl.h b/include/gsl.h index b78c6e2..009c777 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -267,6 +267,9 @@ public: maybe_null_ret& operator=(const T& p) { if (ptr_ != p) { ptr_ = p; } return *this; } maybe_null_ret& operator=(const maybe_null_ret& rhs) = default; + bool operator==(const T& rhs) const { return ptr_ == rhs; } + bool operator!=(const T& rhs) const { return ptr_ != rhs; } + bool present() const { return ptr_ != nullptr; } T get() const { return ptr_; } From c4f9b87d96176c32ae609c293816dbbe732f2899 Mon Sep 17 00:00:00 2001 From: Kern Handa Date: Fri, 25 Sep 2015 17:01:29 -0700 Subject: [PATCH 14/59] We should be using standard algorithms where possible. Use of algorithms in the STL should be promoted where possible. Also fixed up some whitespace issues. --- include/array_view.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 26a1641..d8b5cab 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "fail_fast.h" #ifndef _MSC_VER @@ -142,12 +143,7 @@ namespace details } _CONSTEXPR bool operator==(const ConcreteType& rhs) const _NOEXCEPT { - for (unsigned int i = 0; i < rank; ++i) - { - if (elems[i] != rhs.elems[i]) - return false; - } - return true; + return std::equal(elems, elems + rank, rhs.elems); } _CONSTEXPR bool operator!=(const ConcreteType& rhs) const _NOEXCEPT { @@ -160,8 +156,7 @@ namespace details _CONSTEXPR ConcreteType operator-() const { ConcreteType ret = to_concrete(); - for (unsigned int i = 0; i < rank; ++i) - ret.elems[i] = -ret.elems[i]; + std::transform(ret, ret + rank, ret, std::negate{}); return ret; } _CONSTEXPR ConcreteType operator+(const ConcreteType& rhs) const From 96e57571813988af7ec1706d91a56e01d577782f Mon Sep 17 00:00:00 2001 From: Seth Cantrell Date: Sat, 26 Sep 2015 18:00:54 -0400 Subject: [PATCH 15/59] Add .clang-format file To have any hope of achieving consistent formatting there needs to be a standard and a mechanism for enforcing it. This is a first step in that direction. This format specification is intended to mimic the existing style insofar as the current source has any consistent style. For example the determination as to whether ref qualifiers should bind to the type or variable name was made by trying both and seeing which produced fewer changes. One exception is the use of tabs vs. spaces, which was decided based on a comment by neilmacintosh [here][1]. To use clang-format with Visual Studio [download][2] and install the clang-format plugin. In VS ctrl-r, ctrl-f formats the current line or text selection. [1]: https://github.com/Microsoft/GSL/issues/55 [2]: http:llvm.org/builds/ --- .clang-format | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..bef7ebc --- /dev/null +++ b/.clang-format @@ -0,0 +1,21 @@ +ColumnLimit: 0 + +UseTab: Never +IndentWidth: 4 +AccessModifierOffset: -4 +NamespaceIndentation: Inner + +BreakBeforeBraces: Allman +AlwaysBreakTemplateDeclarations: false +BreakConstructorInitializersBeforeComma: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +AllowShortBlocksOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true + +PointerAlignment: Left +AlignConsecutiveAssignments: false +AlignTrailingComments: false + +SpaceAfterCStyleCast: true From 437791e504462b2585808a717b61e084692638be Mon Sep 17 00:00:00 2001 From: saurabh singh Date: Sun, 27 Sep 2015 16:11:12 +0530 Subject: [PATCH 16/59] GSL::finally can make use of move semantics for eg consider this case [code] string value = "someVeryLongErrorMessageIAm"; finally([value] { PrintErrorMessage(value); } [/code] With the current changes before the call to PrintErrorMessage there will be 3 calls to copy constructor for string(1 when it's captured in closure, 2nd when finally is called and 3rd when it's passed to Final_act . With my patch there will be 1 call to the copy constructor and 2 to the move constructor for the scenario in example, so 2 potential deep copies will be saved for some objects. Validated that code builds from root, and all tests pass after my change. Also validated that indeed copy constructor calls are saved for objects that support move semantics. --- include/gsl.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 09a46c7..23b62a9 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -50,7 +50,7 @@ template class Final_act { public: - explicit Final_act(F f) : f_(f) {} + explicit Final_act(F f) : f_(std::move(f)) {} Final_act(const Final_act&& other) : f_(other.f_) {} Final_act(const Final_act&) = delete; @@ -64,7 +64,10 @@ private: // finally() - convenience function to generate a Final_act template -Final_act finally(F f) { return Final_act(f); } +Final_act finally(const F &f) { return Final_act(f); } + +template +Final_act finally(F &&f) { return Final_act(std::forward(f)); } // narrow_cast(): a searchable way to do narrowing casts of values template From 2b6d90436f3f0b0444efc918203663367e823b65 Mon Sep 17 00:00:00 2001 From: Kern Handa Date: Fri, 25 Sep 2015 09:41:40 -0700 Subject: [PATCH 17/59] not_null and maybe_null variants should only work on nullptr-assignable types. This is in accordance with the GSL.View guidance on not_null and maybe_null types in the CppCoreGuidelines document. --- include/gsl.h | 3 +++ tests/maybenull_tests.cpp | 13 +++++++++++++ tests/notnull_tests.cpp | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/include/gsl.h b/include/gsl.h index 23b62a9..fed3b6c 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -108,6 +108,7 @@ typename Cont::value_type& at(Cont& cont, size_t index) { fail_fast_assert(index template class not_null { + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: not_null(T t) : ptr_(t) { ensure_invariant(); } @@ -168,6 +169,7 @@ private: template class maybe_null_dbg { + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: maybe_null_dbg() : ptr_(nullptr), tested_(false) {} @@ -243,6 +245,7 @@ private: template class maybe_null_ret { + static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: maybe_null_ret() : ptr_(nullptr) {} maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 0a9d891..4b74114 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -16,6 +16,7 @@ #include #include +#include using namespace Guide; @@ -27,12 +28,24 @@ SUITE(MaybeNullTests) { TEST(TestMaybeNull1) { +#ifdef CONFIRM_COMPILATION_ERRORS + // Forbid non-nullptr assignable types + maybe_null_ret> f_ret(std::vector{1}); + maybe_null_ret> f_ret(std::vector{1}); + maybe_null_ret z_ret(10); + maybe_null_dbg> y_dbg({1,2}); + maybe_null_dbg z_dbg(10); + maybe_null_dbg> y_dbg({1,2}); +#endif int n = 5; maybe_null_dbg opt_n(&n); int result = 0; bool threw = false; CHECK_THROW(result = *opt_n, fail_fast); + + maybe_null_ret> x_ret(std::make_shared(10)); // shared_ptr is nullptr assignable + maybe_null_dbg> x_dbg(std::make_shared(10)); // shared_ptr is nullptr assignable } TEST(TestMaybeNull2) diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 008cbb3..7232840 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -16,6 +16,7 @@ #include #include +#include using namespace Guide; @@ -48,11 +49,18 @@ SUITE(NotNullTests) not_null p; // yay...does not compile! std::unique_ptr up = std::make_unique(120); not_null p = up; + + // Forbid non-nullptr assignable types + not_null> f(std::vector{1}); + not_null z(10); + not_null> y({1,2}); #endif int i = 12; auto rp = RefCounted(&i); not_null p(rp); CHECK(p.get() == &i); + + not_null> x(std::make_shared(10)); // shared_ptr is nullptr assignable } TEST(TestNotNullCasting) From fb91393bb205ea6a19cda4c92db5899519be9bdc Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Sun, 27 Sep 2015 16:25:43 -0700 Subject: [PATCH 18/59] Fixing size_t/int mismatch in loops. --- include/array_view.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index e40918d..68a3cf0 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -1067,7 +1067,7 @@ public: } bounds_iterator& operator--() _NOEXCEPT { - for (int i = rank; i-- > 0;) + for (size_t i = rank; i-- > 0;) { if (curr[i]-- > 0) { @@ -1335,7 +1335,7 @@ namespace details auto extents = bnd.index_bounds(); typename Bounds::index_type stride; stride[Bounds::rank - 1] = 1; - for (int i = Bounds::rank - 2; i >= 0; --i) + for (size_t i = Bounds::rank - 2; i >= 0; --i) stride[i] = stride[i + 1] * extents[i + 1]; return stride; } @@ -2035,7 +2035,7 @@ private: fail_fast_assert(strides[rank - 1] == 1, "Only strided arrays with regular strides can be resized"); fail_fast_assert(strides[rank - 2] >= d && (strides[rank - 2] % d == 0), "The strides must have contiguous chunks of memory that can contain a multiple of new type elements"); - for (int i = rank - 2; i >= 0; --i) + for (size_t i = rank - 2; i >= 0; --i) { fail_fast_assert((strides[i] >= strides[i + 1]) && (strides[i] % strides[i + 1] == 0), "Only strided arrays with regular strides can be resized"); } From 99746e2d57a3068d1130dce4bf5b1e46a86cf9d2 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Sun, 27 Sep 2015 16:53:58 -0700 Subject: [PATCH 19/59] Correct fix for int/size_t mismatch. --- include/array_view.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 68a3cf0..038b6e4 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -1328,15 +1328,15 @@ namespace details return bnd.strides(); } - // Make a stride vector from bounds, assuming continugous memory. + // Make a stride vector from bounds, assuming contiguous memory. template _CONSTEXPR std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT { auto extents = bnd.index_bounds(); typename Bounds::index_type stride; stride[Bounds::rank - 1] = 1; - for (size_t i = Bounds::rank - 2; i >= 0; --i) - stride[i] = stride[i + 1] * extents[i + 1]; + for (size_t i = Bounds::rank - 1; Bounds::rank > 1 && i > 0; --i) + stride[i-1] = stride[i] * extents[i]; return stride; } @@ -2035,10 +2035,8 @@ private: fail_fast_assert(strides[rank - 1] == 1, "Only strided arrays with regular strides can be resized"); fail_fast_assert(strides[rank - 2] >= d && (strides[rank - 2] % d == 0), "The strides must have contiguous chunks of memory that can contain a multiple of new type elements"); - for (size_t i = rank - 2; i >= 0; --i) - { - fail_fast_assert((strides[i] >= strides[i + 1]) && (strides[i] % strides[i + 1] == 0), "Only strided arrays with regular strides can be resized"); - } + for (size_t i = rank - 1; i > 0; --i) + fail_fast_assert((strides[i-1] >= strides[i]) && (strides[i-1] % strides[i] == 0), "Only strided arrays with regular strides can be resized"); index_type ret = strides / d; ret[rank - 1] = 1; From bb169976da75c4c8a30b403ffc8ff887d72a75bf Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Sun, 27 Sep 2015 18:06:51 -0700 Subject: [PATCH 20/59] Fixed leak in owner<> test. Ha ha ha! --- tests/owner_tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 430b31a..d985533 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -33,6 +33,7 @@ SUITE(owner_tests) CHECK(*p == 120); f(p); CHECK(*p == 121); + delete p; } } From 783eaabf9d7b40403540f2164fb096c3150d4c94 Mon Sep 17 00:00:00 2001 From: Kern Handa Date: Mon, 28 Sep 2015 07:35:18 +0000 Subject: [PATCH 21/59] Add various copy assignment operators to not_null and maybe_null_*. Also removed unused constant member variable that seemed to be there to prevent maybe_null_* being used with anything other than a pointer, which is being taken care of with a static_assert now. --- include/gsl.h | 129 +++++++++++++++++++++++++++----------- tests/maybenull_tests.cpp | 38 +++++++++++ tests/notnull_tests.cpp | 11 +++- 3 files changed, 138 insertions(+), 40 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index fed3b6c..bf3573e 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -111,21 +111,27 @@ class not_null static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: not_null(T t) : ptr_(t) { ensure_invariant(); } - - // deleting these two prevents compilation when initialized with a nullptr or literal 0 - not_null(std::nullptr_t) = delete; - not_null(int) = delete; + not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; } not_null(const not_null &other) = default; + not_null& operator=(const not_null &other) = default; template ::value>> - not_null(const not_null &other) : ptr_(other.get()) + not_null(const not_null &other) { + *this = other; } - not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; } + template ::value>> + not_null& operator=(const not_null &other) + { + ptr_ = other.get(); + return *this; + } // prevents compilation when someone attempts to assign a nullptr + not_null(std::nullptr_t) = delete; + not_null(int) = delete; not_null& operator=(std::nullptr_t) = delete; not_null& operator=(int) = delete; @@ -166,26 +172,18 @@ private: // // Describes an optional pointer - provides symmetry with not_null // +template +class maybe_null_ret; + template class maybe_null_dbg { static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); public: maybe_null_dbg() : ptr_(nullptr), tested_(false) {} + maybe_null_dbg(std::nullptr_t) : ptr_(nullptr), tested_(false) {} maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {} - maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {} - - template ::value>> - maybe_null_dbg(const not_null &other) : ptr_(other.get()), tested_(false) - { - } - - template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) - { - } - maybe_null_dbg& operator=(const T& p) { if (ptr_ != p) @@ -196,6 +194,8 @@ public: return *this; } + + maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {} maybe_null_dbg& operator=(const maybe_null_dbg& rhs) { if (this != &rhs) @@ -206,6 +206,43 @@ public: return *this; } + + template ::value>> + maybe_null_dbg(const not_null &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const not_null &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + + template ::value>> + maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const maybe_null_dbg &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + + template ::value>> + maybe_null_dbg(const maybe_null_ret &other) : ptr_(other.get()), tested_(false) {} + + template ::value>> + maybe_null_dbg& operator=(const maybe_null_ret &other) + { + ptr_ = other.get(); + tested_ = false; + return *this; + } + + bool present() const { tested_ = true; return ptr_ != nullptr; } bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; } @@ -225,8 +262,6 @@ public: T operator->() const { return get(); } private: - const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type - // unwanted operators...pointers only point to single objects! // TODO ensure all arithmetic ops on this type are unavailable maybe_null_dbg& operator++() = delete; @@ -249,27 +284,46 @@ class maybe_null_ret public: maybe_null_ret() : ptr_(nullptr) {} maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} + maybe_null_ret(const T& p) : ptr_(p) {} + maybe_null_ret& operator=(const T& p) { ptr_ = p; return *this; } + maybe_null_ret(const maybe_null_ret& rhs) = default; - - template ::value>> - maybe_null_ret(const not_null &other) : ptr_(other.get()) - { - } - - template ::value>> - maybe_null_ret(const maybe_null_ret &other) : ptr_(other.get()) - { - } - - template ::value>> - maybe_null_ret(const maybe_null_dbg &other) : ptr_(other.get()) - { - } - - maybe_null_ret& operator=(const T& p) { if (ptr_ != p) { ptr_ = p; } return *this; } maybe_null_ret& operator=(const maybe_null_ret& rhs) = default; + template ::value>> + maybe_null_ret(const not_null &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const not_null &other) + { + ptr_ = other.get(); + return *this; + } + + + template ::value>> + maybe_null_ret(const maybe_null_ret &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const maybe_null_ret &other) + { + ptr_ = other.get(); + return *this; + } + + + template ::value>> + maybe_null_ret(const maybe_null_dbg &other) : ptr_(other.get()) {} + + template ::value>> + maybe_null_ret& operator=(const maybe_null_dbg &other) + { + ptr_ = other.get(); + return *this; + } + + bool present() const { return ptr_ != nullptr; } T get() const { return ptr_; } @@ -289,7 +343,6 @@ private: maybe_null_ret& operator-(size_t) = delete; maybe_null_ret& operator-=(size_t) = delete; - const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type T ptr_; }; diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 4b74114..d6b53f0 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -17,6 +17,7 @@ #include #include #include +#include using namespace Guide; @@ -254,6 +255,43 @@ SUITE(MaybeNullTests) // Make sure we no longer throw here CHECK(p1.get() != nullptr); } + + TEST(TestMaybeNullAssignmentOps) + { + MyBase base; + MyDerived derived; + Unrelated unrelated; + + not_null nnBase(&base); + not_null nnDerived(&derived); + not_null nnUnrelated(&unrelated); + + maybe_null_ret mnBase_ret1(&base), mnBase_ret2; + mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret + mnBase_ret2 = nnBase; // maybe_null_ret = not_null + + maybe_null_ret mnDerived_ret(&derived); + mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret + mnBase_ret1 = &derived; // maybe_null_ret = U; + mnBase_ret1 = nnDerived; // maybe_null_ret = not_null + + maybe_null_ret mnUnrelated_ret; + mnUnrelated_ret = &unrelated; // maybe_null_ret = T + + maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; + mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg + mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null + + maybe_null_dbg mnDerived_dbg(&derived); + CHECK(mnDerived_dbg.present()); + mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg + + mnBase_dbg1 = &derived; // maybe_null_dbg = U; + mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null + + maybe_null_dbg mnUnrelated_dbg; + mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T + } } int main(int, const char *[]) diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 7232840..46011b6 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -65,12 +65,19 @@ SUITE(NotNullTests) TEST(TestNotNullCasting) { - MyDerived derived; + MyBase base; + MyDerived derived; + Unrelated unrelated; + not_null u = &unrelated; not_null p = &derived; - not_null q = p; + not_null q = &base; + q = p; // allowed with heterogeneous copy ctor CHECK(q == p); #ifdef CONFIRM_COMPILATION_ERRORS + q = u; // no viable conversion possible between MyBase* and Unrelated* + p = q; // not possible to implicitly convert MyBase* to MyDerived* + not_null r = p; not_null s = reinterpret_cast(p); #endif From 4e596761eb0ae42ff032c44c22dba9be5adc8733 Mon Sep 17 00:00:00 2001 From: Gabriel Dos Reis Date: Mon, 28 Sep 2015 04:43:50 -0700 Subject: [PATCH 22/59] Update list of known platforms where GSL was successfully tested --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a32e89f..7d96dec 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ The test suite that exercises GSL has been built and passes successfully on the * GNU/Linux using GCC 5.1 * OS X Yosemite using Xcode with AppleClang 7.0.0.7000072 * OS X Yosemite using GCC-5.2.0 +* FreeBSD 10.x with Clang/LLVM 3.6 > If you successfully port GSL to another platform, we would love to hear from you. Please submit an issue to let us know. Also please consider contributing any changes that were necessary back to this project to benefit the wider community. From 6554e83c79e680500691cb2b3411c3c14d82623f Mon Sep 17 00:00:00 2001 From: Gabriel Dos Reis Date: Mon, 28 Sep 2015 05:10:44 -0700 Subject: [PATCH 23/59] Macro expand `constexpr` to nothing under MSVC Replace `_CONSTEXPR` with plain `constexpr`. --- include/array_view.h | 334 ++++++++++++++++++++++--------------------- 1 file changed, 169 insertions(+), 165 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 038b6e4..8bfdc69 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -30,10 +30,9 @@ #include #include "fail_fast.h" -#ifndef _MSC_VER -#define _CONSTEXPR constexpr -#else -#define _CONSTEXPR +#if defined(_MSC_VER) +#pragma push_macro("constexpr") +#define constexpr /* nothing */ #endif #pragma push_macro("_NOEXCEPT") @@ -88,24 +87,24 @@ namespace details using const_reference = const ValueType&; using value_type = ValueType; static const size_t rank = Rank; - _CONSTEXPR coordinate_facade() _NOEXCEPT + constexpr coordinate_facade() _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); } - _CONSTEXPR coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT + constexpr coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); for (size_t i = 0; i < rank; ++i) elems[i] = values[i]; } - _CONSTEXPR coordinate_facade(value_type e0) _NOEXCEPT + constexpr coordinate_facade(value_type e0) _NOEXCEPT { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); static_assert(rank == 1, "This constructor can only be used with rank == 1."); elems[0] = e0; } // Preconditions: il.size() == rank - _CONSTEXPR coordinate_facade(std::initializer_list il) + constexpr coordinate_facade(std::initializer_list il) { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); fail_fast_assert(il.size() == rank, "The size of the initializer list must match the rank of the array"); @@ -115,10 +114,10 @@ namespace details } } - _CONSTEXPR coordinate_facade(const coordinate_facade & other) = default; + constexpr coordinate_facade(const coordinate_facade & other) = default; template - _CONSTEXPR coordinate_facade(const coordinate_facade & other) + constexpr coordinate_facade(const coordinate_facade & other) { for (size_t i = 0; i < rank; ++i) { @@ -129,18 +128,18 @@ namespace details protected: coordinate_facade& operator=(const coordinate_facade& rhs) = default; // Preconditions: component_idx < rank - _CONSTEXPR reference operator[](size_t component_idx) + constexpr reference operator[](size_t component_idx) { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } // Preconditions: component_idx < rank - _CONSTEXPR const_reference operator[](size_t component_idx) const + constexpr const_reference operator[](size_t component_idx) const { fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } - _CONSTEXPR bool operator==(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator==(const ConcreteType& rhs) const _NOEXCEPT { for (size_t i = 0; i < rank; ++i) { @@ -149,94 +148,94 @@ namespace details } return true; } - _CONSTEXPR bool operator!=(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator!=(const ConcreteType& rhs) const _NOEXCEPT { return !(to_concrete() == rhs); } - _CONSTEXPR ConcreteType operator+() const _NOEXCEPT + constexpr ConcreteType operator+() const _NOEXCEPT { return to_concrete(); } - _CONSTEXPR ConcreteType operator-() const + constexpr ConcreteType operator-() const { ConcreteType ret = to_concrete(); for (size_t i = 0; i < rank; ++i) ret.elems[i] = -ret.elems[i]; return ret; } - _CONSTEXPR ConcreteType operator+(const ConcreteType& rhs) const + constexpr ConcreteType operator+(const ConcreteType& rhs) const { ConcreteType ret = to_concrete(); ret += rhs; return ret; } - _CONSTEXPR ConcreteType operator-(const ConcreteType& rhs) const + constexpr ConcreteType operator-(const ConcreteType& rhs) const { ConcreteType ret = to_concrete(); ret -= rhs; return ret; } - _CONSTEXPR ConcreteType& operator+=(const ConcreteType& rhs) + constexpr ConcreteType& operator+=(const ConcreteType& rhs) { for (size_t i = 0; i < rank; ++i) elems[i] += rhs.elems[i]; return to_concrete(); } - _CONSTEXPR ConcreteType& operator-=(const ConcreteType& rhs) + constexpr ConcreteType& operator-=(const ConcreteType& rhs) { for (size_t i = 0; i < rank; ++i) elems[i] -= rhs.elems[i]; return to_concrete(); } - _CONSTEXPR ConcreteType& operator++() + constexpr ConcreteType& operator++() { static_assert(rank == 1, "This operator can only be used with rank == 1."); ++elems[0]; return to_concrete(); } - _CONSTEXPR ConcreteType operator++(int) + constexpr ConcreteType operator++(int) { static_assert(rank == 1, "This operator can only be used with rank == 1."); ConcreteType ret = to_concrete(); ++(*this); return ret; } - _CONSTEXPR ConcreteType& operator--() + constexpr ConcreteType& operator--() { static_assert(rank == 1, "This operator can only be used with rank == 1."); --elems[0]; return to_concrete(); } - _CONSTEXPR ConcreteType operator--(int) + constexpr ConcreteType operator--(int) { static_assert(rank == 1, "This operator can only be used with rank == 1."); ConcreteType ret = to_concrete(); --(*this); return ret; } - _CONSTEXPR ConcreteType operator*(value_type v) const + constexpr ConcreteType operator*(value_type v) const { ConcreteType ret = to_concrete(); ret *= v; return ret; } - _CONSTEXPR ConcreteType operator/(value_type v) const + constexpr ConcreteType operator/(value_type v) const { ConcreteType ret = to_concrete(); ret /= v; return ret; } - friend _CONSTEXPR ConcreteType operator*(value_type v, const ConcreteType& rhs) + friend constexpr ConcreteType operator*(value_type v, const ConcreteType& rhs) { return rhs * v; } - _CONSTEXPR ConcreteType& operator*=(value_type v) + constexpr ConcreteType& operator*=(value_type v) { for (size_t i = 0; i < rank; ++i) elems[i] *= v; return to_concrete(); } - _CONSTEXPR ConcreteType& operator/=(value_type v) + constexpr ConcreteType& operator/=(value_type v) { for (size_t i = 0; i < rank; ++i) elems[i] /= v; @@ -244,11 +243,11 @@ namespace details } value_type elems[rank] = {}; private: - _CONSTEXPR const ConcreteType& to_concrete() const _NOEXCEPT + constexpr const ConcreteType& to_concrete() const _NOEXCEPT { return static_cast(*this); } - _CONSTEXPR ConcreteType& to_concrete() _NOEXCEPT + constexpr ConcreteType& to_concrete() _NOEXCEPT { return static_cast(*this); } @@ -286,17 +285,17 @@ public: using const_reference = typename Base::const_reference; using size_type = typename Base::value_type; using value_type = typename Base::value_type; - _CONSTEXPR index() _NOEXCEPT : Base(){} - _CONSTEXPR index(const value_type (&values)[rank]) _NOEXCEPT : Base(values) {} - _CONSTEXPR index(std::initializer_list il) : Base(il) {} + constexpr index() _NOEXCEPT : Base(){} + constexpr index(const value_type (&values)[rank]) _NOEXCEPT : Base(values) {} + constexpr index(std::initializer_list il) : Base(il) {} - _CONSTEXPR index(const index &) = default; + constexpr index(const index &) = default; template - _CONSTEXPR index(const index &other) : Base(other) + constexpr index(const index &other) : Base(other) { } - _CONSTEXPR static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) _NOEXCEPT { value_type (&arr)[rank] = (value_type(&)[rank])(*(other.elems + 1)); return index(arr); @@ -329,124 +328,124 @@ public: using size_type = ValueType; using value_type = ValueType; - _CONSTEXPR index() _NOEXCEPT : value(0) + constexpr index() _NOEXCEPT : value(0) { } - _CONSTEXPR index(value_type e0) _NOEXCEPT : value(e0) + constexpr index(value_type e0) _NOEXCEPT : value(e0) { } - _CONSTEXPR index(const value_type(&values)[1]) _NOEXCEPT : index(values[0]) + constexpr index(const value_type(&values)[1]) _NOEXCEPT : index(values[0]) { } // Preconditions: il.size() == rank - _CONSTEXPR index(std::initializer_list il) + constexpr index(std::initializer_list il) { fail_fast_assert(il.size() == rank, "Size of the initializer list must match the rank of the array"); value = begin(il)[0]; } - _CONSTEXPR index(const index &) = default; + constexpr index(const index &) = default; template - _CONSTEXPR index(const index<1, OtherValueType> & other) + constexpr index(const index<1, OtherValueType> & other) { fail_fast_assert(other.value <= details::SizeTypeTraits::max_value); value = static_cast(other.value); } - _CONSTEXPR static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) _NOEXCEPT { return other.elems[1]; } // Preconditions: component_idx < rank - _CONSTEXPR reference operator[](size_type component_idx) _NOEXCEPT + constexpr reference operator[](size_type component_idx) _NOEXCEPT { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); return value; } // Preconditions: component_idx < rank - _CONSTEXPR const_reference operator[](size_type component_idx) const _NOEXCEPT + constexpr const_reference operator[](size_type component_idx) const _NOEXCEPT { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); return value; } - _CONSTEXPR bool operator==(const index& rhs) const _NOEXCEPT + constexpr bool operator==(const index& rhs) const _NOEXCEPT { return value == rhs.value; } - _CONSTEXPR bool operator!=(const index& rhs) const _NOEXCEPT + constexpr bool operator!=(const index& rhs) const _NOEXCEPT { return !(*this == rhs); } - _CONSTEXPR index operator+() const _NOEXCEPT + constexpr index operator+() const _NOEXCEPT { return *this; } - _CONSTEXPR index operator-() const _NOEXCEPT + constexpr index operator-() const _NOEXCEPT { return index(-value); } - _CONSTEXPR index operator+(const index& rhs) const _NOEXCEPT + constexpr index operator+(const index& rhs) const _NOEXCEPT { return index(value + rhs.value); } - _CONSTEXPR index operator-(const index& rhs) const _NOEXCEPT + constexpr index operator-(const index& rhs) const _NOEXCEPT { return index(value - rhs.value); } - _CONSTEXPR index& operator+=(const index& rhs) _NOEXCEPT + constexpr index& operator+=(const index& rhs) _NOEXCEPT { value += rhs.value; return *this; } - _CONSTEXPR index& operator-=(const index& rhs) _NOEXCEPT + constexpr index& operator-=(const index& rhs) _NOEXCEPT { value -= rhs.value; return *this; } - _CONSTEXPR index& operator++() _NOEXCEPT + constexpr index& operator++() _NOEXCEPT { ++value; return *this; } - _CONSTEXPR index operator++(int) _NOEXCEPT + constexpr index operator++(int) _NOEXCEPT { index ret = *this; ++(*this); return ret; } - _CONSTEXPR index& operator--() _NOEXCEPT + constexpr index& operator--() _NOEXCEPT { --value; return *this; } - _CONSTEXPR index operator--(int) _NOEXCEPT + constexpr index operator--(int) _NOEXCEPT { index ret = *this; --(*this); return ret; } - _CONSTEXPR index operator*(value_type v) const _NOEXCEPT + constexpr index operator*(value_type v) const _NOEXCEPT { return index(value * v); } - _CONSTEXPR index operator/(value_type v) const _NOEXCEPT + constexpr index operator/(value_type v) const _NOEXCEPT { return index(value / v); } - _CONSTEXPR index& operator*=(value_type v) _NOEXCEPT + constexpr index& operator*=(value_type v) _NOEXCEPT { value *= v; return *this; } - _CONSTEXPR index& operator/=(value_type v) _NOEXCEPT + constexpr index& operator/=(value_type v) _NOEXCEPT { value /= v; return *this; } - friend _CONSTEXPR index operator*(value_type v, const index& rhs) _NOEXCEPT + friend constexpr index operator*(value_type v, const index& rhs) _NOEXCEPT { return index(rhs * v); } @@ -777,7 +776,7 @@ class static_bounds && details::SizeTypeTraits::max_value <= SIZE_MAX, "SizeType must be an integral type and its numeric limits must be smaller than SIZE_MAX"); MyRanges m_ranges; - _CONSTEXPR static_bounds(const MyRanges & range) : m_ranges(range) { } + constexpr static_bounds(const MyRanges & range) : m_ranges(range) { } template friend class static_bounds; @@ -794,72 +793,72 @@ public: using sliced_type = static_bounds; using mapping_type = contiguous_mapping_tag; public: - _CONSTEXPR static_bounds(const static_bounds &) = default; + constexpr static_bounds(const static_bounds &) = default; template , details::BoundsRanges >::value>> - _CONSTEXPR static_bounds(const static_bounds &other): + constexpr static_bounds(const static_bounds &other): m_ranges(other.m_ranges) { } - _CONSTEXPR static_bounds(std::initializer_list il) : m_ranges(il.begin()) + constexpr static_bounds(std::initializer_list il) : m_ranges(il.begin()) { fail_fast_assert(MyRanges::DynamicNum == il.size(), "Size of the initializer list must match the rank of the array"); fail_fast_assert(m_ranges.totalSize() <= details::SizeTypeTraits::max_value, "Size of the range is larger than the max element of the size type"); } - _CONSTEXPR static_bounds() = default; + constexpr static_bounds() = default; - _CONSTEXPR static_bounds & operator = (const static_bounds & otherBounds) + constexpr static_bounds & operator = (const static_bounds & otherBounds) { new(&m_ranges) MyRanges (otherBounds.m_ranges); return *this; } - _CONSTEXPR sliced_type slice() const _NOEXCEPT + constexpr sliced_type slice() const _NOEXCEPT { return sliced_type{static_cast &>(m_ranges)}; } - _CONSTEXPR size_type stride() const _NOEXCEPT + constexpr size_type stride() const _NOEXCEPT { return rank > 1 ? slice().size() : 1; } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { return static_cast(m_ranges.totalSize()); } - _CONSTEXPR size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const _NOEXCEPT { return static_cast(m_ranges.totalSize()); } - _CONSTEXPR size_type linearize(const index_type & idx) const + constexpr size_type linearize(const index_type & idx) const { return m_ranges.linearize(idx); } - _CONSTEXPR bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const _NOEXCEPT { return m_ranges.contains(idx) != -1; } - _CONSTEXPR size_type operator[](size_t index) const _NOEXCEPT + constexpr size_type operator[](size_t index) const _NOEXCEPT { return m_ranges.elementNum(index); } template - _CONSTEXPR size_type extent() const _NOEXCEPT + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return details::createTypeListIndexer(m_ranges).template get().elementNum(); } - _CONSTEXPR index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const _NOEXCEPT { index_type extents; m_ranges.serialize(extents); @@ -867,23 +866,23 @@ public: } template - _CONSTEXPR bool operator == (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator == (const static_bounds & rhs) const _NOEXCEPT { return this->size() == rhs.size(); } template - _CONSTEXPR bool operator != (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator != (const static_bounds & rhs) const _NOEXCEPT { return !(*this == rhs); } - _CONSTEXPR const_iterator begin() const _NOEXCEPT + constexpr const_iterator begin() const _NOEXCEPT { return const_iterator(*this); } - _CONSTEXPR const_iterator end() const _NOEXCEPT + constexpr const_iterator end() const _NOEXCEPT { index_type boundary; m_ranges.serialize(boundary); @@ -913,43 +912,43 @@ public: static const size_t static_size = dynamic_range; using sliced_type = std::conditional_t, void>; using mapping_type = generalized_mapping_tag; - _CONSTEXPR strided_bounds(const strided_bounds &) = default; + constexpr strided_bounds(const strided_bounds &) = default; template - _CONSTEXPR strided_bounds(const strided_bounds &other) + constexpr strided_bounds(const strided_bounds &other) : Base(other), m_strides(other.strides) { } - _CONSTEXPR strided_bounds(const index_type &extents, const index_type &strides) + constexpr strided_bounds(const index_type &extents, const index_type &strides) : m_strides(strides) { for (size_t i = 0; i < rank; i++) Base::elems[i] = extents[i]; } - _CONSTEXPR strided_bounds(const value_type(&values)[rank], index_type strides) + constexpr strided_bounds(const value_type(&values)[rank], index_type strides) : Base(values), m_strides(std::move(strides)) { } - _CONSTEXPR index_type strides() const _NOEXCEPT + constexpr index_type strides() const _NOEXCEPT { return m_strides; } - _CONSTEXPR size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const _NOEXCEPT { size_type ret = 0; for (size_t i = 0; i < rank; ++i) ret += (Base::elems[i] - 1) * m_strides[i]; return ret + 1; } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { size_type ret = 1; for (size_t i = 0; i < rank; ++i) ret *= Base::elems[i]; return ret; } - _CONSTEXPR bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const _NOEXCEPT { for (size_t i = 0; i < rank; ++i) { @@ -958,7 +957,7 @@ public: } return true; } - _CONSTEXPR size_type linearize(const index_type & idx) const + constexpr size_type linearize(const index_type & idx) const { size_type ret = 0; for (size_t i = 0; i < rank; i++) @@ -968,22 +967,22 @@ public: } return ret; } - _CONSTEXPR size_type stride() const _NOEXCEPT + constexpr size_type stride() const _NOEXCEPT { return m_strides[0]; } template 1), typename Ret = std::enable_if_t> - _CONSTEXPR sliced_type slice() const + constexpr sliced_type slice() const { return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; } template - _CONSTEXPR size_type extent() const _NOEXCEPT + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); return Base::elems[Dim]; } - _CONSTEXPR index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const _NOEXCEPT { return index_type(Base::elems); } @@ -1323,14 +1322,14 @@ bounds_iterator operator+(typename bounds_iterator::differ namespace details { template - _CONSTEXPR std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT { return bnd.strides(); } // Make a stride vector from bounds, assuming contiguous memory. template - _CONSTEXPR std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT { auto extents = bnd.index_bounds(); typename Bounds::index_type stride; @@ -1380,30 +1379,30 @@ private: bounds_type m_bounds; public: - _CONSTEXPR bounds_type bounds() const _NOEXCEPT + constexpr bounds_type bounds() const _NOEXCEPT { return m_bounds; } template - _CONSTEXPR size_type extent() const _NOEXCEPT + constexpr size_type extent() const _NOEXCEPT { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return m_bounds.template extent(); } - _CONSTEXPR size_type size() const _NOEXCEPT + constexpr size_type size() const _NOEXCEPT { return m_bounds.size(); } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return m_pdata[m_bounds.linearize(idx)]; } - _CONSTEXPR pointer data() const _NOEXCEPT + constexpr pointer data() const _NOEXCEPT { return m_pdata; } template 1), typename Ret = std::enable_if_t> - _CONSTEXPR Ret operator[](size_type idx) const + constexpr Ret operator[](size_type idx) const { fail_fast_assert(idx < m_bounds.size(), "index is out of bounds of the array"); const size_type ridx = idx * m_bounds.stride(); @@ -1412,78 +1411,78 @@ public: return Ret {m_pdata + ridx, m_bounds.slice()}; } - _CONSTEXPR operator bool () const _NOEXCEPT + constexpr operator bool () const _NOEXCEPT { return m_pdata != nullptr; } - _CONSTEXPR iterator begin() const + constexpr iterator begin() const { return iterator {this, true}; } - _CONSTEXPR iterator end() const + constexpr iterator end() const { return iterator {this}; } - _CONSTEXPR const_iterator cbegin() const + constexpr const_iterator cbegin() const { return const_iterator {reinterpret_cast *>(this), true}; } - _CONSTEXPR const_iterator cend() const + constexpr const_iterator cend() const { return const_iterator {reinterpret_cast *>(this)}; } - _CONSTEXPR reverse_iterator rbegin() const + constexpr reverse_iterator rbegin() const { return reverse_iterator {end()}; } - _CONSTEXPR reverse_iterator rend() const + constexpr reverse_iterator rend() const { return reverse_iterator {begin()}; } - _CONSTEXPR const_reverse_iterator crbegin() const + constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator {cend()}; } - _CONSTEXPR const_reverse_iterator crend() const + constexpr const_reverse_iterator crend() const { return const_reverse_iterator {cbegin()}; } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator== (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator== (const basic_array_view & other) const _NOEXCEPT { return m_bounds.size() == other.m_bounds.size() && (m_pdata == other.m_pdata || std::equal(this->begin(), this->end(), other.begin())); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator!= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator!= (const basic_array_view & other) const _NOEXCEPT { return !(*this == other); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator< (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator< (const basic_array_view & other) const _NOEXCEPT { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator<= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator<= (const basic_array_view & other) const _NOEXCEPT { return !(other < *this); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator> (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator> (const basic_array_view & other) const _NOEXCEPT { return (other < *this); } template , std::remove_cv_t>::value>> - _CONSTEXPR bool operator>= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator>= (const basic_array_view & other) const _NOEXCEPT { return !(*this < other); } @@ -1492,27 +1491,27 @@ public: template ::value && std::is_convertible::value>> - _CONSTEXPR basic_array_view(const basic_array_view & other ) _NOEXCEPT + constexpr basic_array_view(const basic_array_view & other ) _NOEXCEPT : m_pdata(other.m_pdata), m_bounds(other.m_bounds) { } protected: - _CONSTEXPR basic_array_view(pointer data, bounds_type bound) _NOEXCEPT + constexpr basic_array_view(pointer data, bounds_type bound) _NOEXCEPT : m_pdata(data) , m_bounds(std::move(bound)) { fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0); } template - _CONSTEXPR basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) _NOEXCEPT + constexpr basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) _NOEXCEPT : m_pdata(reinterpret_cast(data)) , m_bounds(std::move(bound)) { fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0); } template - _CONSTEXPR basic_array_view as_array_view(const DestBounds &bounds) + constexpr basic_array_view as_array_view(const DestBounds &bounds) { details::verifyBoundsReshape(m_bounds, bounds); return {m_pdata, bounds}; @@ -1661,22 +1660,22 @@ public: public: // basic - _CONSTEXPR array_view(pointer ptr, bounds_type bounds) : Base(ptr, std::move(bounds)) + constexpr array_view(pointer ptr, bounds_type bounds) : Base(ptr, std::move(bounds)) { } - _CONSTEXPR array_view(std::nullptr_t) : Base(nullptr, bounds_type{}) + constexpr array_view(std::nullptr_t) : Base(nullptr, bounds_type{}) { } - _CONSTEXPR array_view(std::nullptr_t, size_type size) : Base(nullptr, bounds_type{}) + constexpr array_view(std::nullptr_t, size_type size) : Base(nullptr, bounds_type{}) { fail_fast_assert(size == 0); } // default template > - _CONSTEXPR array_view() : Base(nullptr, bounds_type()) + constexpr array_view() : Base(nullptr, bounds_type()) { } @@ -1684,7 +1683,7 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value>> - _CONSTEXPR array_view(T * const & data, size_type size) : Base(data, typename Helper::bounds_type{size}) + constexpr array_view(T * const & data, size_type size) : Base(data, typename Helper::bounds_type{size}) { } @@ -1692,7 +1691,7 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value>> - _CONSTEXPR array_view (T (&arr)[N]) : Base(arr, typename Helper::bounds_type()) + constexpr array_view (T (&arr)[N]) : Base(arr, typename Helper::bounds_type()) { } @@ -1700,19 +1699,19 @@ public: template , typename Dummy = std::enable_if_t::value && std::is_convertible::value >> - _CONSTEXPR array_view(T(&arr)[N], size_type size) : Base(arr, typename Helper::bounds_type{ size }) + constexpr array_view(T(&arr)[N], size_type size) : Base(arr, typename Helper::bounds_type{ size }) { fail_fast_assert(size <= N); } // from std array template , typename Base::bounds_type>::value>> - _CONSTEXPR array_view (std::array, N> & arr) : Base(arr.data(), static_bounds()) + constexpr array_view (std::array, N> & arr) : Base(arr.data(), static_bounds()) { } template , typename Base::bounds_type>::value && std::is_const::value>> - _CONSTEXPR array_view (const std::array, N> & arr) : Base(arr.data(), static_bounds()) + constexpr array_view (const std::array, N> & arr) : Base(arr.data(), static_bounds()) { } @@ -1721,7 +1720,7 @@ public: template ::value && details::LessThan::value>> // remove literal 0 case - _CONSTEXPR array_view (pointer begin, Ptr end) : Base(begin, details::newBoundsHelper(static_cast(end) - begin)) + constexpr array_view (pointer begin, Ptr end) : Base(begin, details::newBoundsHelper(static_cast(end) - begin)) { } @@ -1732,12 +1731,12 @@ public: && std::is_convertible, typename Base::bounds_type>::value && std::is_same().size(), *std::declval().data())>, DataType>::value> > - _CONSTEXPR array_view (Cont& cont) : Base(static_cast(cont.data()), details::newBoundsHelper(cont.size())) + constexpr array_view (Cont& cont) : Base(static_cast(cont.data()), details::newBoundsHelper(cont.size())) { } - _CONSTEXPR array_view(const array_view &) = default; + constexpr array_view(const array_view &) = default; // convertible template ::value_type, static_bounds::size_type, OtherDimensions...>>, typename Dummy = std::enable_if_t::value> > - _CONSTEXPR array_view(const array_view &av) : Base(static_cast::Base &>(av)) {} // static_cast is required + constexpr array_view(const array_view &av) : Base(static_cast::Base &>(av)) {} // static_cast is required // reshape template - _CONSTEXPR array_view as_array_view(Dimensions2... dims) + constexpr array_view as_array_view(Dimensions2... dims) { static_assert(sizeof...(Dimensions2) > 0, "the target array_view must have at least one dimension."); using BoundsType = typename array_view::bounds_type; @@ -1760,7 +1759,7 @@ public: // to bytes array template ::value_type>>::value> - _CONSTEXPR auto as_bytes() const _NOEXCEPT -> + constexpr auto as_bytes() const _NOEXCEPT -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1768,7 +1767,7 @@ public: } template ::value_type>>::value> - _CONSTEXPR auto as_writeable_bytes() const _NOEXCEPT -> + constexpr auto as_writeable_bytes() const _NOEXCEPT -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1778,7 +1777,7 @@ public: // from bytes array template::value, typename Dummy = std::enable_if_t> - _CONSTEXPR auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0), "Target type must be standard layout and its size must match the byte array size"); @@ -1787,7 +1786,7 @@ public: } template::value, typename Dummy = std::enable_if_t> - _CONSTEXPR auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0), "Target type must be standard layout and its size must match the byte array size"); @@ -1797,79 +1796,79 @@ public: // section on linear space template - _CONSTEXPR array_view first() const _NOEXCEPT + constexpr array_view first() const _NOEXCEPT { static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); // ensures we only check condition when needed return { this->data(), Count }; } - _CONSTEXPR array_view first(size_type count) const _NOEXCEPT + constexpr array_view first(size_type count) const _NOEXCEPT { fail_fast_assert(count <= this->size()); return { this->data(), count }; } template - _CONSTEXPR array_view last() const _NOEXCEPT + constexpr array_view last() const _NOEXCEPT { static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); return { this->data() + this->size() - Count, Count }; } - _CONSTEXPR array_view last(size_type count) const _NOEXCEPT + constexpr array_view last(size_type count) const _NOEXCEPT { fail_fast_assert(count <= this->size()); return { this->data() + this->size() - count, count }; } template - _CONSTEXPR array_view sub() const _NOEXCEPT + constexpr array_view sub() const _NOEXCEPT { static_assert(bounds_type::static_size == dynamic_range || ((Offset == 0 || Offset <= bounds_type::static_size) && Offset + Count <= bounds_type::static_size), "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || ((Offset == 0 || Offset <= this->size()) && Offset + Count <= this->size())); return { this->data() + Offset, Count }; } - _CONSTEXPR array_view sub(size_type offset, size_type count = dynamic_range) const _NOEXCEPT + constexpr array_view sub(size_type offset, size_type count = dynamic_range) const _NOEXCEPT { fail_fast_assert((offset == 0 || offset <= this->size()) && (count == dynamic_range || (offset + count) <= this->size())); return { this->data() + offset, count == dynamic_range ? this->length() - offset : count }; } // size - _CONSTEXPR size_type length() const _NOEXCEPT + constexpr size_type length() const _NOEXCEPT { return this->size(); } - _CONSTEXPR size_type used_length() const _NOEXCEPT + constexpr size_type used_length() const _NOEXCEPT { return length(); } - _CONSTEXPR size_type bytes() const _NOEXCEPT + constexpr size_type bytes() const _NOEXCEPT { return sizeof(value_type) * this->size(); } - _CONSTEXPR size_type used_bytes() const _NOEXCEPT + constexpr size_type used_bytes() const _NOEXCEPT { return bytes(); } // section - _CONSTEXPR strided_array_view section(index_type origin, index_type extents) const + constexpr strided_array_view section(index_type origin, index_type extents) const { size_type size = this->bounds().total_size() - this->bounds().linearize(origin); return{ &this->operator[](origin), size, strided_bounds {extents, details::make_stride(Base::bounds())} }; } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return Base::operator[](idx); } template 1), typename Dummy = std::enable_if_t> - _CONSTEXPR array_view operator[](size_type idx) const + constexpr array_view operator[](size_type idx) const { auto ret = Base::operator[](idx); return{ ret.data(), ret.bounds() }; @@ -1884,53 +1883,53 @@ public: }; template -_CONSTEXPR auto as_array_view(T * const & ptr, dim... args) -> array_view, Dimensions...> +constexpr auto as_array_view(T * const & ptr, dim... args) -> array_view, Dimensions...> { return {reinterpret_cast*>(ptr), details::static_as_array_view_helper>(args..., details::Sep{})}; } template -_CONSTEXPR auto as_array_view (T * arr, size_t len) -> typename details::ArrayViewArrayTraits::type +constexpr auto as_array_view (T * arr, size_t len) -> typename details::ArrayViewArrayTraits::type { return {arr, len}; } template -_CONSTEXPR auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits::type +constexpr auto as_array_view (T (&arr)[N]) -> typename details::ArrayViewArrayTraits::type { return {arr}; } template -_CONSTEXPR array_view as_array_view(const std::array &arr) +constexpr array_view as_array_view(const std::array &arr) { return {arr}; } template -_CONSTEXPR array_view as_array_view(const std::array &&) = delete; +constexpr array_view as_array_view(const std::array &&) = delete; template -_CONSTEXPR array_view as_array_view(std::array &arr) +constexpr array_view as_array_view(std::array &arr) { return {arr}; } template -_CONSTEXPR array_view as_array_view(T *begin, T *end) +constexpr array_view as_array_view(T *begin, T *end) { return {begin, end}; } template -_CONSTEXPR auto as_array_view(Cont &arr) -> std::enable_if_t>::value, +constexpr auto as_array_view(Cont &arr) -> std::enable_if_t>::value, array_view, dynamic_range>> { return {arr.data(), arr.size()}; } template -_CONSTEXPR auto as_array_view(Cont &&arr) -> std::enable_if_t>::value, +constexpr auto as_array_view(Cont &&arr) -> std::enable_if_t>::value, array_view, dynamic_range>> = delete; template @@ -1977,7 +1976,7 @@ public: typename OtherBaseType = basic_array_view::value_type, strided_bounds::size_type>>, typename Dummy = std::enable_if_t::value> > - _CONSTEXPR strided_array_view(const strided_array_view &av): Base(static_cast::Base &>(av)) // static_cast is required + constexpr strided_array_view(const strided_array_view &av): Base(static_cast::Base &>(av)) // static_cast is required { } @@ -1998,13 +1997,13 @@ public: return { &this->operator[](origin), size, bounds_type {extents, details::make_stride(Base::bounds())}}; } - _CONSTEXPR reference operator[](const index_type& idx) const + constexpr reference operator[](const index_type& idx) const { return Base::operator[](idx); } template 1), typename Dummy = std::enable_if_t> - _CONSTEXPR strided_array_view operator[](size_type idx) const + constexpr strided_array_view operator[](size_type idx) const { auto ret = Base::operator[](idx); return{ ret.data(), ret.bounds().total_size(), ret.bounds() }; @@ -2282,6 +2281,11 @@ general_array_view_iterator operator+(typename general_array_view_ite } // namespace Guide +#if defined(_MSC_VER) +#undef constexpr +#pragma pop_macro("constexpr") +#endif + #if defined(_MSC_VER) && _MSC_VER <= 1800 #pragma warning(pop) #endif // _MSC_VER <= 1800 From 3402b92ef67571688e927b96c67f2ed7b79e97dc Mon Sep 17 00:00:00 2001 From: Kosov Eugene Date: Mon, 28 Sep 2015 21:20:02 +0300 Subject: [PATCH 24/59] fix clang -Wunused-parameter warnings --- include/array_view.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 8bfdc69..ca4f897 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -548,7 +548,7 @@ namespace details // TODO : following signature is for work around VS bug template - BoundsRanges (const OtherType &, bool firstLevel) {} + BoundsRanges (const OtherType &, bool /* firstLevel */) {} BoundsRanges(const SizeType * const) { } BoundsRanges() = default; @@ -593,7 +593,7 @@ namespace details BoundsRanges() : m_bound(0) {} template - BoundsRanges(const BoundsRanges &other, bool firstLevel = true) : + BoundsRanges(const BoundsRanges &other, bool /* firstLevel */ = true) : Base(static_cast&>(other), false), m_bound (static_cast(other.totalSize())) { } @@ -764,7 +764,7 @@ class bounds_iterator; template class static_bounds { public: - static_bounds(const details::BoundsRanges &empty) { + static_bounds(const details::BoundsRanges &) { } }; @@ -2021,7 +2021,7 @@ private: } template > - static index_type resize_stride(const index_type& strides, size_t d, void *p = 0) + static index_type resize_stride(const index_type& strides, size_t , void * = 0) { fail_fast_assert(strides[rank - 1] == 1, "Only strided arrays with regular strides can be resized"); From e46160c18ec633ee7f20d1d32df85c783bba18f6 Mon Sep 17 00:00:00 2001 From: Kosov Eugene Date: Mon, 28 Sep 2015 23:20:28 +0300 Subject: [PATCH 25/59] it's better to pass a small (e.g. 16 bytes) object by value then by const reference --- include/string_view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/string_view.h b/include/string_view.h index e683c7a..164c3ac 100644 --- a/include/string_view.h +++ b/include/string_view.h @@ -137,7 +137,7 @@ basic_string_view::type, dy // to_string() allow (explicit) conversions from string_view to string // template -std::basic_string::type> to_string(const basic_string_view& view) +std::basic_string::type> to_string(basic_string_view view) { return{ view.data(), view.length() }; } From a46d6fcf0d69a20f630cd590ba0867a1cf6a8cb4 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Mon, 28 Sep 2015 15:17:37 -0700 Subject: [PATCH 26/59] Fix issue #49 --- include/gsl.h | 4 +- tests/maybenull_tests.cpp | 80 +++++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 1405993..a73db6b 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -223,12 +223,12 @@ public: template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) {} + maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.ptr_), tested_(false) {} template ::value>> maybe_null_dbg& operator=(const maybe_null_dbg &other) { - ptr_ = other.get(); + ptr_ = other.ptr_; tested_ = false; return *this; } diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index d6b53f0..a889e52 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -256,42 +256,64 @@ SUITE(MaybeNullTests) CHECK(p1.get() != nullptr); } - TEST(TestMaybeNullAssignmentOps) - { - MyBase base; - MyDerived derived; - Unrelated unrelated; + template + void TestMaybeNullAssignmentOpsHelper() + { + MyBase base; + MyDerived derived; + Unrelated unrelated; - not_null nnBase(&base); - not_null nnDerived(&derived); - not_null nnUnrelated(&unrelated); + not_null nnBase(&base); + not_null nnDerived(&derived); + not_null nnUnrelated(&unrelated); - maybe_null_ret mnBase_ret1(&base), mnBase_ret2; - mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret - mnBase_ret2 = nnBase; // maybe_null_ret = not_null + maybe_null_type::type mnBase_ret1(&base), mnBase_ret2; + mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret + mnBase_ret2 = nnBase; // maybe_null_ret = not_null - maybe_null_ret mnDerived_ret(&derived); - mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret - mnBase_ret1 = &derived; // maybe_null_ret = U; - mnBase_ret1 = nnDerived; // maybe_null_ret = not_null + maybe_null_type::type mnDerived_ret(&derived); + mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret + mnBase_ret1 = &derived; // maybe_null_ret = U; + mnBase_ret1 = nnDerived; // maybe_null_ret = not_null - maybe_null_ret mnUnrelated_ret; - mnUnrelated_ret = &unrelated; // maybe_null_ret = T + maybe_null_type::type mnUnrelated_ret; + mnUnrelated_ret = &unrelated; // maybe_null_ret = T - maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; - mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg - mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null + maybe_null_type::type mnBase_dbg1(&base), mnBase_dbg2; + mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg + mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null - maybe_null_dbg mnDerived_dbg(&derived); - CHECK(mnDerived_dbg.present()); - mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg - - mnBase_dbg1 = &derived; // maybe_null_dbg = U; - mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null + maybe_null_type::type mnDerived_dbg(&derived); + CHECK(mnDerived_dbg.present()); + mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg - maybe_null_dbg mnUnrelated_dbg; - mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T - } + mnBase_dbg1 = &derived; // maybe_null_dbg = U; + mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null + + maybe_null_type::type mnUnrelated_dbg; + mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T + } + + struct maybe_null_ret_type + { + template + using type = maybe_null_ret; + }; + struct maybe_null_dbg_type + { + template + using type = maybe_null_dbg; + }; + + TEST(TestMaybeNullRetAssignmentOps) + { + TestMaybeNullAssignmentOpsHelper(); + } + + TEST(TestMaybeNullDbgAssignmentOps) + { + TestMaybeNullAssignmentOpsHelper(); + } } int main(int, const char *[]) From b29566628e180ce100f9cbdb08d4ba56ab650a01 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Mon, 28 Sep 2015 18:26:35 -0700 Subject: [PATCH 27/59] Revert "Fix issue #49" This reverts commit a46d6fcf0d69a20f630cd590ba0867a1cf6a8cb4. --- include/gsl.h | 4 +- tests/maybenull_tests.cpp | 80 ++++++++++++++------------------------- 2 files changed, 31 insertions(+), 53 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index a73db6b..1405993 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -223,12 +223,12 @@ public: template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.ptr_), tested_(false) {} + maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) {} template ::value>> maybe_null_dbg& operator=(const maybe_null_dbg &other) { - ptr_ = other.ptr_; + ptr_ = other.get(); tested_ = false; return *this; } diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index a889e52..d6b53f0 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -256,64 +256,42 @@ SUITE(MaybeNullTests) CHECK(p1.get() != nullptr); } - template - void TestMaybeNullAssignmentOpsHelper() - { - MyBase base; - MyDerived derived; - Unrelated unrelated; + TEST(TestMaybeNullAssignmentOps) + { + MyBase base; + MyDerived derived; + Unrelated unrelated; - not_null nnBase(&base); - not_null nnDerived(&derived); - not_null nnUnrelated(&unrelated); + not_null nnBase(&base); + not_null nnDerived(&derived); + not_null nnUnrelated(&unrelated); - maybe_null_type::type mnBase_ret1(&base), mnBase_ret2; - mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret - mnBase_ret2 = nnBase; // maybe_null_ret = not_null + maybe_null_ret mnBase_ret1(&base), mnBase_ret2; + mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret + mnBase_ret2 = nnBase; // maybe_null_ret = not_null - maybe_null_type::type mnDerived_ret(&derived); - mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret - mnBase_ret1 = &derived; // maybe_null_ret = U; - mnBase_ret1 = nnDerived; // maybe_null_ret = not_null + maybe_null_ret mnDerived_ret(&derived); + mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret + mnBase_ret1 = &derived; // maybe_null_ret = U; + mnBase_ret1 = nnDerived; // maybe_null_ret = not_null - maybe_null_type::type mnUnrelated_ret; - mnUnrelated_ret = &unrelated; // maybe_null_ret = T + maybe_null_ret mnUnrelated_ret; + mnUnrelated_ret = &unrelated; // maybe_null_ret = T - maybe_null_type::type mnBase_dbg1(&base), mnBase_dbg2; - mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg - mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null + maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; + mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg + mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null - maybe_null_type::type mnDerived_dbg(&derived); - CHECK(mnDerived_dbg.present()); - mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg + maybe_null_dbg mnDerived_dbg(&derived); + CHECK(mnDerived_dbg.present()); + mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg + + mnBase_dbg1 = &derived; // maybe_null_dbg = U; + mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null - mnBase_dbg1 = &derived; // maybe_null_dbg = U; - mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null - - maybe_null_type::type mnUnrelated_dbg; - mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T - } - - struct maybe_null_ret_type - { - template - using type = maybe_null_ret; - }; - struct maybe_null_dbg_type - { - template - using type = maybe_null_dbg; - }; - - TEST(TestMaybeNullRetAssignmentOps) - { - TestMaybeNullAssignmentOpsHelper(); - } - - TEST(TestMaybeNullDbgAssignmentOps) - { - TestMaybeNullAssignmentOpsHelper(); - } + maybe_null_dbg mnUnrelated_dbg; + mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T + } } int main(int, const char *[]) From 83333419de094f305f1bcaa1e12f7ed801c0cbfa Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Mon, 28 Sep 2015 18:34:04 -0700 Subject: [PATCH 28/59] Add test that reproduces issue --- tests/maybenull_tests.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index d6b53f0..944307e 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -178,13 +178,19 @@ SUITE(MaybeNullTests) maybe_null q = p; CHECK(q == p); + maybe_null_dbg pdbg = &derived; + CHECK(pdbg.present()); + + maybe_null_dbg qdbg = pdbg; + CHECK(qdbg == pdbg); + #ifdef CONFIRM_COMPILATION_ERRORS maybe_null r = p; maybe_null s = reinterpret_cast(p); #endif maybe_null_dbg t = reinterpret_cast(p.get()); - CHECK_THROW((void)(void*)t.get(), fail_fast); + CHECK_THROW((void)(void*)t.get(), fail_fast); maybe_null_dbg u = reinterpret_cast(p.get()); CHECK(u.present()); CHECK((void*)p.get() == (void*)u.get()); From 444bf9640a91c674a5812704e9e1159f0efbda1d Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Mon, 28 Sep 2015 18:49:53 -0700 Subject: [PATCH 29/59] Fix issue #49 --- include/gsl.h | 4 ++-- tests/maybenull_tests.cpp | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 1405993..a73db6b 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -223,12 +223,12 @@ public: template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.get()), tested_(false) {} + maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.ptr_), tested_(false) {} template ::value>> maybe_null_dbg& operator=(const maybe_null_dbg &other) { - ptr_ = other.get(); + ptr_ = other.ptr_; tested_ = false; return *this; } diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 944307e..661b26a 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -289,9 +289,7 @@ SUITE(MaybeNullTests) mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null maybe_null_dbg mnDerived_dbg(&derived); - CHECK(mnDerived_dbg.present()); mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg - mnBase_dbg1 = &derived; // maybe_null_dbg = U; mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null From 422e7164d53627650d2772c08c27b6b65920bc49 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Mon, 28 Sep 2015 23:40:25 -0500 Subject: [PATCH 30/59] Fixing move constructor of Final_act to take non-const r-value reference and move properly from other Final_act object so that correctness is not dependent on copy elison. --- include/gsl.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index a73db6b..6de3780 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -50,16 +50,17 @@ template class Final_act { public: - explicit Final_act(F f) : f_(std::move(f)) {} - - Final_act(const Final_act&& other) : f_(other.f_) {} + explicit Final_act(F f) : f_(std::move(f)), invoke_(true) {} + + Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other._invoke = false; } Final_act(const Final_act&) = delete; Final_act& operator=(const Final_act&) = delete; - - ~Final_act() { f_(); } + + ~Final_act() { if (invoke_) f_(); } private: F f_; + bool invoke_; }; // finally() - convenience function to generate a Final_act From 1d11cd1ed13593f5892aff847dfbb42b85a04037 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Tue, 29 Sep 2015 00:00:21 -0500 Subject: [PATCH 31/59] Fixing typo in move constructor implementation that resulted in compile error during tests. --- include/gsl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl.h b/include/gsl.h index 6de3780..95116dc 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -52,7 +52,7 @@ class Final_act public: explicit Final_act(F f) : f_(std::move(f)), invoke_(true) {} - Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other._invoke = false; } + Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } Final_act(const Final_act&) = delete; Final_act& operator=(const Final_act&) = delete; From ae24c0fe06f92a2a77fb4dbd0098335519a54390 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Tue, 29 Sep 2015 00:03:15 -0500 Subject: [PATCH 32/59] Added test that Final_act object can be moved properly. While this is not a common case, it may happen if the user calls finally and the compiler fails to perform RVO. --- tests/utils_tests.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 0dc4809..66b6d14 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -37,6 +37,20 @@ SUITE(utils_tests) CHECK(i == 1); } + TEST(finally_lambda_move) + { + int i = 0; + { + auto _1 = finally([&]() {f(i);}); + { + auto _2 = std::move(_1); + CHECK(i == 0); + } + CHECK(i == 1); + } + CHECK(i == 1); + } + TEST(finally_function_with_bind) { int i = 0; From ef626fd33a2f22ac917394995270da225dbc3c5f Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Tue, 29 Sep 2015 16:41:37 -0700 Subject: [PATCH 33/59] Renamed namespace to 'gsl'. Renamed macro to configure testing. --- include/array_view.h | 8 ++++---- include/fail_fast.h | 6 +++--- include/gsl.h | 8 ++++---- include/string_view.h | 4 ++-- tests/CMakeLists.txt | 2 +- tests/array_view_tests.cpp | 6 +++--- tests/assertion_tests.cpp | 2 +- tests/at_tests.cpp | 2 +- tests/bounds_tests.cpp | 2 +- tests/maybenull_tests.cpp | 2 +- tests/notnull_tests.cpp | 2 +- tests/owner_tests.cpp | 2 +- tests/string_view_tests.cpp | 2 +- tests/utils_tests.cpp | 2 +- 14 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index ca4f897..9db9d53 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -39,7 +39,7 @@ #ifndef _NOEXCEPT -#ifdef SAFER_CPP_TESTING +#ifdef GSL_THROWS_FOR_TESTING #define _NOEXCEPT #else #define _NOEXCEPT noexcept @@ -47,7 +47,7 @@ #else // _NOEXCEPT -#ifdef SAFER_CPP_TESTING +#ifdef GSL_THROWS_FOR_TESTING #undef _NOEXCEPT #define _NOEXCEPT #endif @@ -59,7 +59,7 @@ #pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior #endif // _MSC_VER <= 1800 -namespace Guide { +namespace gsl { /* ** begin definitions of index and bounds @@ -2279,7 +2279,7 @@ general_array_view_iterator operator+(typename general_array_view_ite return rhs + n; } -} // namespace Guide +} // namespace gsl #if defined(_MSC_VER) #undef constexpr diff --git a/include/fail_fast.h b/include/fail_fast.h index 78a5102..477bace 100644 --- a/include/fail_fast.h +++ b/include/fail_fast.h @@ -22,14 +22,14 @@ #include #include -namespace Guide +namespace gsl { // // Having "fail fast" result in an exception makes unit testing // the GSL classes that rely upon it much simpler. // -#if defined(SAFER_CPP_TESTING) +#if defined(GSL_THROWS_FOR_TESTING) struct fail_fast : public std::runtime_error { @@ -45,7 +45,7 @@ inline void fail_fast_assert(bool cond, const char* const message) { if (!cond) inline void fail_fast_assert(bool cond) { if (!cond) std::terminate(); } inline void fail_fast_assert(bool cond, const char* const) { if (!cond) std::terminate(); } -#endif // SAFER_CPP_TESTING +#endif // GSL_THROWS_FOR_TESTING } diff --git a/include/gsl.h b/include/gsl.h index 95116dc..5ae4df6 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -23,7 +23,7 @@ #include "string_view.h" // zstring, string_view, zstring_builder... #include -namespace Guide +namespace gsl { // @@ -38,8 +38,8 @@ using owner = T; // // GSL.assert: assertions // -#define Expects(x) Guide::fail_fast_assert((x)) -#define Ensures(x) Guide::fail_fast_assert((x)) +#define Expects(x) gsl::fail_fast_assert((x)) +#define Ensures(x) gsl::fail_fast_assert((x)) // // GSL.util: utilities @@ -354,6 +354,6 @@ private: template using maybe_null = maybe_null_ret; -} // namespace Guide +} // namespace gsl #endif // GSL_GSL_H diff --git a/include/string_view.h b/include/string_view.h index 164c3ac..4076d52 100644 --- a/include/string_view.h +++ b/include/string_view.h @@ -22,7 +22,7 @@ #include "array_view.h" #include -namespace Guide +namespace gsl { // // czstring and wzstring @@ -164,7 +164,7 @@ public: size_type length() const { return sv_.length(); } pointer assume0() const { return data(); } - string_view_type ensure_z() const { return Guide::ensure_z(sv_); } + string_view_type ensure_z() const { return gsl::ensure_z(sv_); } iterator begin() const { return sv_.begin(); } iterator end() const { return sv_.end(); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0415db3..774413f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,7 @@ include_directories( ./unittest-cpp ) -add_definitions(-DSAFER_CPP_TESTING) +add_definitions(-DGSL_THROWS_FOR_TESTING) if(MSVC14 OR MSVC12) # has the support we need # remove unnecessary warnings about unchecked iterators diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index ba251e8..918df9e 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -27,7 +27,7 @@ using namespace std; -using namespace Guide; +using namespace gsl; namespace { @@ -261,8 +261,8 @@ SUITE(array_view_tests) int a[30][4][5]; auto av = as_array_view(a); - auto sub = av.section({15, 0, 0}, Guide::index<3>{2, 2, 2}); - auto subsub = sub.section({1, 0, 0}, Guide::index<3>{1, 1, 1}); + auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2}); + auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1}); } TEST(array_view_section) diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index 012a043..acd381a 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -17,7 +17,7 @@ #include #include -using namespace Guide; +using namespace gsl; SUITE(assertion_tests) { diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 6a86307..d27dd9d 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -19,7 +19,7 @@ #include using namespace std; -using namespace Guide; +using namespace gsl; SUITE(at_tests) { diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp index b14a113..c3f549f 100644 --- a/tests/bounds_tests.cpp +++ b/tests/bounds_tests.cpp @@ -19,7 +19,7 @@ #include using namespace std; -using namespace Guide;; +using namespace gsl;; namespace { diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp index 661b26a..74d449f 100644 --- a/tests/maybenull_tests.cpp +++ b/tests/maybenull_tests.cpp @@ -19,7 +19,7 @@ #include #include -using namespace Guide; +using namespace gsl; struct MyBase { bool foo() { return true; } }; struct MyDerived : public MyBase {}; diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 46011b6..a9624b8 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -18,7 +18,7 @@ #include #include -using namespace Guide; +using namespace gsl; struct MyBase {}; struct MyDerived : public MyBase {}; diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index d985533..47c223a 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -18,7 +18,7 @@ #include #include -using namespace Guide; +using namespace gsl; SUITE(owner_tests) { diff --git a/tests/string_view_tests.cpp b/tests/string_view_tests.cpp index c382cf0..84b7f3f 100644 --- a/tests/string_view_tests.cpp +++ b/tests/string_view_tests.cpp @@ -20,7 +20,7 @@ #include using namespace std; -using namespace Guide; +using namespace gsl; SUITE(string_view_tests) { diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 66b6d14..3090c7d 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -18,7 +18,7 @@ #include #include -using namespace Guide; +using namespace gsl; SUITE(utils_tests) { From 761554f68d8dfaa19f89b7b2a861035dbd9ff46d Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Tue, 29 Sep 2015 16:54:00 -0700 Subject: [PATCH 34/59] Correct misleading text in static_assert. Fixes issue #67. --- include/array_view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/array_view.h b/include/array_view.h index 9db9d53..c581760 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -77,7 +77,7 @@ namespace details class coordinate_facade { static_assert(std::is_integral::value - && sizeof(ValueType) <= sizeof(size_t), "ValueType must be unsigned integral type!"); + && sizeof(ValueType) <= sizeof(size_t), "ValueType must be an integral type!"); static_assert(Rank > 0, "Rank must be greater than 0!"); template From e8ff01e543fdb6a0be8f47d66c8279e7fcc72136 Mon Sep 17 00:00:00 2001 From: RicoAntonioFelix Date: Wed, 30 Sep 2015 12:50:42 -0400 Subject: [PATCH 35/59] Commit to address issue #103... --- include/fail_fast.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/fail_fast.h b/include/fail_fast.h index 477bace..b9982eb 100644 --- a/include/fail_fast.h +++ b/include/fail_fast.h @@ -20,7 +20,10 @@ #define GSL_FAIL_FAST_H #include + +#if defined(GSL_THROWS_FOR_TESTING) #include +#endif namespace gsl { From d06f7ff779824ca26b3c1daf0b31837334c9cf25 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Wed, 30 Sep 2015 12:39:18 -0700 Subject: [PATCH 36/59] Renamed Final_act to final_act as per issue #91. --- include/gsl.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 5ae4df6..5d4c840 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -45,30 +45,30 @@ using owner = T; // GSL.util: utilities // -// Final_act allows you to ensure something gets run at the end of a scope +// final_act allows you to ensure something gets run at the end of a scope template -class Final_act +class final_act { public: - explicit Final_act(F f) : f_(std::move(f)), invoke_(true) {} + explicit final_act(F f) : f_(std::move(f)), invoke_(true) {} - Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } - Final_act(const Final_act&) = delete; - Final_act& operator=(const Final_act&) = delete; + final_act(final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } + final_act(const final_act&) = delete; + final_act& operator=(const final_act&) = delete; - ~Final_act() { if (invoke_) f_(); } + ~final_act() { if (invoke_) f_(); } private: F f_; bool invoke_; }; -// finally() - convenience function to generate a Final_act +// finally() - convenience function to generate a final_act template -Final_act finally(const F &f) { return Final_act(f); } +final_act finally(const F &f) { return final_act(f); } template -Final_act finally(F &&f) { return Final_act(std::forward(f)); } +final_act finally(F &&f) { return final_act(std::forward(f)); } // narrow_cast(): a searchable way to do narrowing casts of values template From 831c6926df2dd17a691abf7d84137435ff172025 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Wed, 30 Sep 2015 15:10:24 -0700 Subject: [PATCH 37/59] Adding noexcept to finally, final_act, narrow_cast. Fixes #92. --- include/gsl.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index 5d4c840..e15ca5c 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -50,13 +50,13 @@ template class final_act { public: - explicit final_act(F f) : f_(std::move(f)), invoke_(true) {} + explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {} - final_act(final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } + final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } final_act(const final_act&) = delete; final_act& operator=(const final_act&) = delete; - ~final_act() { if (invoke_) f_(); } + ~final_act() noexcept { if (invoke_) f_(); } private: F f_; @@ -65,14 +65,14 @@ private: // finally() - convenience function to generate a final_act template -final_act finally(const F &f) { return final_act(f); } +final_act finally(const F &f) noexcept { return final_act(f); } template -final_act finally(F &&f) { return final_act(std::forward(f)); } +final_act finally(F &&f) noexcept { return final_act(std::forward(f)); } // narrow_cast(): a searchable way to do narrowing casts of values template -T narrow_cast(U u) { return static_cast(u); } +T narrow_cast(U u) noexcept { return static_cast(u); } struct narrowing_error : public std::exception {}; // narrow() : a checked version of narrow_cast() that throws if the cast changed the value From d531680a31919bf2220585d22f13f90203606004 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Wed, 30 Sep 2015 21:54:08 -0700 Subject: [PATCH 38/59] Improved macros used for non-compliant compilers. --- include/array_view.h | 418 ++++++++++++++++++++++--------------------- include/gsl.h | 48 +++++ 2 files changed, 262 insertions(+), 204 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index c581760..3fc675e 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -30,35 +30,35 @@ #include #include "fail_fast.h" -#if defined(_MSC_VER) +#ifdef _MSC_VER + +// No MSVC does constexpr fully yet #pragma push_macro("constexpr") #define constexpr /* nothing */ + + +// VS 2013 workarounds +#if _MSC_VER <= 1800 + +// noexcept is not understood +#ifndef GSL_THROWS_FOR_TESTING +#define noexcept /* nothing */ #endif -#pragma push_macro("_NOEXCEPT") - -#ifndef _NOEXCEPT - -#ifdef GSL_THROWS_FOR_TESTING -#define _NOEXCEPT -#else -#define _NOEXCEPT noexcept -#endif - -#else // _NOEXCEPT - -#ifdef GSL_THROWS_FOR_TESTING -#undef _NOEXCEPT -#define _NOEXCEPT -#endif - -#endif // _NOEXCEPT - -#if defined(_MSC_VER) && _MSC_VER <= 1800 +// turn off some misguided warnings #pragma warning(push) #pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior + #endif // _MSC_VER <= 1800 +#endif // _MSC_VER + +// In order to test the library, we need it to throw exceptions that we can catch +#ifdef GSL_THROWS_FOR_TESTING +#define noexcept /* nothing */ +#endif // GSL_THROWS_FOR_TESTING + + namespace gsl { /* @@ -87,17 +87,17 @@ namespace details using const_reference = const ValueType&; using value_type = ValueType; static const size_t rank = Rank; - constexpr coordinate_facade() _NOEXCEPT + constexpr coordinate_facade() noexcept { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); } - constexpr coordinate_facade(const value_type(&values)[rank]) _NOEXCEPT + constexpr coordinate_facade(const value_type(&values)[rank]) noexcept { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); for (size_t i = 0; i < rank; ++i) elems[i] = values[i]; } - constexpr coordinate_facade(value_type e0) _NOEXCEPT + constexpr coordinate_facade(value_type e0) noexcept { static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); static_assert(rank == 1, "This constructor can only be used with rank == 1."); @@ -139,7 +139,7 @@ namespace details fail_fast_assert(component_idx < rank, "Component index must be less than rank"); return elems[component_idx]; } - constexpr bool operator==(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator==(const ConcreteType& rhs) const noexcept { for (size_t i = 0; i < rank; ++i) { @@ -148,11 +148,11 @@ namespace details } return true; } - constexpr bool operator!=(const ConcreteType& rhs) const _NOEXCEPT + constexpr bool operator!=(const ConcreteType& rhs) const noexcept { return !(to_concrete() == rhs); } - constexpr ConcreteType operator+() const _NOEXCEPT + constexpr ConcreteType operator+() const noexcept { return to_concrete(); } @@ -243,11 +243,11 @@ namespace details } value_type elems[rank] = {}; private: - constexpr const ConcreteType& to_concrete() const _NOEXCEPT + constexpr const ConcreteType& to_concrete() const noexcept { return static_cast(*this); } - constexpr ConcreteType& to_concrete() _NOEXCEPT + constexpr ConcreteType& to_concrete() noexcept { return static_cast(*this); } @@ -259,11 +259,11 @@ namespace details explicit arrow_proxy(T t) : val(t) {} - const T operator*() const _NOEXCEPT + const T operator*() const noexcept { return val; } - const T* operator->() const _NOEXCEPT + const T* operator->() const noexcept { return &val; } @@ -285,8 +285,8 @@ public: using const_reference = typename Base::const_reference; using size_type = typename Base::value_type; using value_type = typename Base::value_type; - constexpr index() _NOEXCEPT : Base(){} - constexpr index(const value_type (&values)[rank]) _NOEXCEPT : Base(values) {} + constexpr index() noexcept : Base(){} + constexpr index(const value_type (&values)[rank]) noexcept : Base(values) {} constexpr index(std::initializer_list il) : Base(il) {} constexpr index(const index &) = default; @@ -295,7 +295,7 @@ public: constexpr index(const index &other) : Base(other) { } - constexpr static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) noexcept { value_type (&arr)[rank] = (value_type(&)[rank])(*(other.elems + 1)); return index(arr); @@ -328,13 +328,13 @@ public: using size_type = ValueType; using value_type = ValueType; - constexpr index() _NOEXCEPT : value(0) + constexpr index() noexcept : value(0) { } - constexpr index(value_type e0) _NOEXCEPT : value(e0) + constexpr index(value_type e0) noexcept : value(e0) { } - constexpr index(const value_type(&values)[1]) _NOEXCEPT : index(values[0]) + constexpr index(const value_type(&values)[1]) noexcept : index(values[0]) { } // Preconditions: il.size() == rank @@ -353,99 +353,99 @@ public: value = static_cast(other.value); } - constexpr static index shift_left(const index& other) _NOEXCEPT + constexpr static index shift_left(const index& other) noexcept { return other.elems[1]; } // Preconditions: component_idx < rank - constexpr reference operator[](size_type component_idx) _NOEXCEPT + constexpr reference operator[](size_type component_idx) noexcept { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); return value; } // Preconditions: component_idx < rank - constexpr const_reference operator[](size_type component_idx) const _NOEXCEPT + constexpr const_reference operator[](size_type component_idx) const noexcept { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); return value; } - constexpr bool operator==(const index& rhs) const _NOEXCEPT + constexpr bool operator==(const index& rhs) const noexcept { return value == rhs.value; } - constexpr bool operator!=(const index& rhs) const _NOEXCEPT + constexpr bool operator!=(const index& rhs) const noexcept { return !(*this == rhs); } - constexpr index operator+() const _NOEXCEPT + constexpr index operator+() const noexcept { return *this; } - constexpr index operator-() const _NOEXCEPT + constexpr index operator-() const noexcept { return index(-value); } - constexpr index operator+(const index& rhs) const _NOEXCEPT + constexpr index operator+(const index& rhs) const noexcept { return index(value + rhs.value); } - constexpr index operator-(const index& rhs) const _NOEXCEPT + constexpr index operator-(const index& rhs) const noexcept { return index(value - rhs.value); } - constexpr index& operator+=(const index& rhs) _NOEXCEPT + constexpr index& operator+=(const index& rhs) noexcept { value += rhs.value; return *this; } - constexpr index& operator-=(const index& rhs) _NOEXCEPT + constexpr index& operator-=(const index& rhs) noexcept { value -= rhs.value; return *this; } - constexpr index& operator++() _NOEXCEPT + constexpr index& operator++() noexcept { ++value; return *this; } - constexpr index operator++(int) _NOEXCEPT + constexpr index operator++(int) noexcept { index ret = *this; ++(*this); return ret; } - constexpr index& operator--() _NOEXCEPT + constexpr index& operator--() noexcept { --value; return *this; } - constexpr index operator--(int) _NOEXCEPT + constexpr index operator--(int) noexcept { index ret = *this; --(*this); return ret; } - constexpr index operator*(value_type v) const _NOEXCEPT + constexpr index operator*(value_type v) const noexcept { return index(value * v); } - constexpr index operator/(value_type v) const _NOEXCEPT + constexpr index operator/(value_type v) const noexcept { return index(value / v); } - constexpr index& operator*=(value_type v) _NOEXCEPT + constexpr index& operator*=(value_type v) noexcept { value *= v; return *this; } - constexpr index& operator/=(value_type v) _NOEXCEPT + constexpr index& operator/=(value_type v) noexcept { value /= v; return *this; } - friend constexpr index operator*(value_type v, const index& rhs) _NOEXCEPT + friend constexpr index operator*(value_type v, const index& rhs) noexcept { return index(rhs * v); } @@ -565,11 +565,11 @@ namespace details return 0; } - size_t totalSize() const _NOEXCEPT { + size_t totalSize() const noexcept { return TotalSize; } - bool operator == (const BoundsRanges &) const _NOEXCEPT + bool operator == (const BoundsRanges &) const noexcept { return true; } @@ -619,22 +619,22 @@ namespace details return static_cast(cur) < static_cast(m_bound) ? cur + last : -1; } - size_t totalSize() const _NOEXCEPT { + size_t totalSize() const noexcept { return m_bound; } - SizeType elementNum() const _NOEXCEPT { + SizeType elementNum() const noexcept { return static_cast(totalSize() / this->Base::totalSize()); } - SizeType elementNum(size_t dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const noexcept{ if (dim > 0) return this->Base::elementNum(dim - 1); else return elementNum(); } - bool operator == (const BoundsRanges & rhs) const _NOEXCEPT + bool operator == (const BoundsRanges & rhs) const noexcept { return m_bound == rhs.m_bound && static_cast(*this) == static_cast(rhs); } @@ -681,22 +681,22 @@ namespace details return static_cast(this->Base::totalSize() * arr[Dim]) + last; } - size_t totalSize() const _NOEXCEPT{ + size_t totalSize() const noexcept{ return CurrentRange * this->Base::totalSize(); } - SizeType elementNum() const _NOEXCEPT{ + SizeType elementNum() const noexcept{ return CurrentRange; } - SizeType elementNum(size_t dim) const _NOEXCEPT{ + SizeType elementNum(size_t dim) const noexcept{ if (dim > 0) return this->Base::elementNum(dim - 1); else return elementNum(); } - bool operator == (const BoundsRanges & rhs) const _NOEXCEPT + bool operator == (const BoundsRanges & rhs) const noexcept { return static_cast(*this) == static_cast(rhs); } @@ -816,22 +816,22 @@ public: return *this; } - constexpr sliced_type slice() const _NOEXCEPT + constexpr sliced_type slice() const noexcept { return sliced_type{static_cast &>(m_ranges)}; } - constexpr size_type stride() const _NOEXCEPT + constexpr size_type stride() const noexcept { return rank > 1 ? slice().size() : 1; } - constexpr size_type size() const _NOEXCEPT + constexpr size_type size() const noexcept { return static_cast(m_ranges.totalSize()); } - constexpr size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const noexcept { return static_cast(m_ranges.totalSize()); } @@ -841,24 +841,24 @@ public: return m_ranges.linearize(idx); } - constexpr bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const noexcept { return m_ranges.contains(idx) != -1; } - constexpr size_type operator[](size_t index) const _NOEXCEPT + constexpr size_type operator[](size_t index) const noexcept { return m_ranges.elementNum(index); } template - constexpr size_type extent() const _NOEXCEPT + constexpr size_type extent() const noexcept { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return details::createTypeListIndexer(m_ranges).template get().elementNum(); } - constexpr index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const noexcept { index_type extents; m_ranges.serialize(extents); @@ -866,23 +866,23 @@ public: } template - constexpr bool operator == (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator == (const static_bounds & rhs) const noexcept { return this->size() == rhs.size(); } template - constexpr bool operator != (const static_bounds & rhs) const _NOEXCEPT + constexpr bool operator != (const static_bounds & rhs) const noexcept { return !(*this == rhs); } - constexpr const_iterator begin() const _NOEXCEPT + constexpr const_iterator begin() const noexcept { return const_iterator(*this); } - constexpr const_iterator end() const _NOEXCEPT + constexpr const_iterator end() const noexcept { index_type boundary; m_ranges.serialize(boundary); @@ -930,25 +930,25 @@ public: : Base(values), m_strides(std::move(strides)) { } - constexpr index_type strides() const _NOEXCEPT + constexpr index_type strides() const noexcept { return m_strides; } - constexpr size_type total_size() const _NOEXCEPT + constexpr size_type total_size() const noexcept { size_type ret = 0; for (size_t i = 0; i < rank; ++i) ret += (Base::elems[i] - 1) * m_strides[i]; return ret + 1; } - constexpr size_type size() const _NOEXCEPT + constexpr size_type size() const noexcept { size_type ret = 1; for (size_t i = 0; i < rank; ++i) ret *= Base::elems[i]; return ret; } - constexpr bool contains(const index_type& idx) const _NOEXCEPT + constexpr bool contains(const index_type& idx) const noexcept { for (size_t i = 0; i < rank; ++i) { @@ -967,7 +967,7 @@ public: } return ret; } - constexpr size_type stride() const _NOEXCEPT + constexpr size_type stride() const noexcept { return m_strides[0]; } @@ -977,20 +977,20 @@ public: return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; } template - constexpr size_type extent() const _NOEXCEPT + constexpr size_type extent() const noexcept { static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); return Base::elems[Dim]; } - constexpr index_type index_bounds() const _NOEXCEPT + constexpr index_type index_bounds() const noexcept { return index_type(Base::elems); } - const_iterator begin() const _NOEXCEPT + const_iterator begin() const noexcept { return const_iterator{ *this }; } - const_iterator end() const _NOEXCEPT + const_iterator end() const noexcept { return const_iterator{ *this, index_bounds() }; } @@ -1024,21 +1024,21 @@ public: using index_type = value_type; using index_size_type = typename IndexType::size_type; template - explicit bounds_iterator(const Bounds & bnd, value_type curr = value_type{}) _NOEXCEPT + explicit bounds_iterator(const Bounds & bnd, value_type curr = value_type{}) noexcept : boundary(bnd.index_bounds()) , curr( std::move(curr) ) { static_assert(is_bounds::value, "Bounds type must be provided"); } - reference operator*() const _NOEXCEPT + reference operator*() const noexcept { return curr; } - pointer operator->() const _NOEXCEPT + pointer operator->() const noexcept { return details::arrow_proxy{ curr }; } - bounds_iterator& operator++() _NOEXCEPT + bounds_iterator& operator++() noexcept { for (size_t i = rank; i-- > 0;) { @@ -1058,13 +1058,13 @@ public: } return *this; } - bounds_iterator operator++(int) _NOEXCEPT + bounds_iterator operator++(int) noexcept { auto ret = *this; ++(*this); return ret; } - bounds_iterator& operator--() _NOEXCEPT + bounds_iterator& operator--() noexcept { for (size_t i = rank; i-- > 0;) { @@ -1082,18 +1082,18 @@ public: fail_fast_assert(false); return *this; } - bounds_iterator operator--(int) _NOEXCEPT + bounds_iterator operator--(int) noexcept { auto ret = *this; --(*this); return ret; } - bounds_iterator operator+(difference_type n) const _NOEXCEPT + bounds_iterator operator+(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret += n; } - bounds_iterator& operator+=(difference_type n) _NOEXCEPT + bounds_iterator& operator+=(difference_type n) noexcept { auto linear_idx = linearize(curr) + n; value_type stride; @@ -1109,32 +1109,32 @@ public: } return *this; } - bounds_iterator operator-(difference_type n) const _NOEXCEPT + bounds_iterator operator-(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret -= n; } - bounds_iterator& operator-=(difference_type n) _NOEXCEPT + bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const bounds_iterator& rhs) const _NOEXCEPT + difference_type operator-(const bounds_iterator& rhs) const noexcept { return linearize(curr) - linearize(rhs.curr); } - reference operator[](difference_type n) const _NOEXCEPT + reference operator[](difference_type n) const noexcept { return *(*this + n); } - bool operator==(const bounds_iterator& rhs) const _NOEXCEPT + bool operator==(const bounds_iterator& rhs) const noexcept { return curr == rhs.curr; } - bool operator!=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const bounds_iterator& rhs) const _NOEXCEPT + bool operator<(const bounds_iterator& rhs) const noexcept { for (size_t i = 0; i < rank; ++i) { @@ -1143,25 +1143,25 @@ public: } return false; } - bool operator<=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const bounds_iterator& rhs) const _NOEXCEPT + bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(bounds_iterator& rhs) _NOEXCEPT + void swap(bounds_iterator& rhs) noexcept { std::swap(boundary, rhs.boundary); std::swap(curr, rhs.curr); } private: - index_size_type linearize(const value_type& idx) const _NOEXCEPT + index_size_type linearize(const value_type& idx) const noexcept { // TODO: Smarter impl. // Check if past-the-end @@ -1218,91 +1218,91 @@ public: using index_size_type = typename index_type::size_type; template - explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) _NOEXCEPT + explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) noexcept : curr( std::move(curr) ) {} - reference operator*() const _NOEXCEPT + reference operator*() const noexcept { return curr; } - pointer operator->() const _NOEXCEPT + pointer operator->() const noexcept { return details::arrow_proxy{ curr }; } - bounds_iterator& operator++() _NOEXCEPT + bounds_iterator& operator++() noexcept { ++curr; return *this; } - bounds_iterator operator++(int) _NOEXCEPT + bounds_iterator operator++(int) noexcept { auto ret = *this; ++(*this); return ret; } - bounds_iterator& operator--() _NOEXCEPT + bounds_iterator& operator--() noexcept { curr--; return *this; } - bounds_iterator operator--(int) _NOEXCEPT + bounds_iterator operator--(int) noexcept { auto ret = *this; --(*this); return ret; } - bounds_iterator operator+(difference_type n) const _NOEXCEPT + bounds_iterator operator+(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret += n; } - bounds_iterator& operator+=(difference_type n) _NOEXCEPT + bounds_iterator& operator+=(difference_type n) noexcept { curr += n; return *this; } - bounds_iterator operator-(difference_type n) const _NOEXCEPT + bounds_iterator operator-(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret -= n; } - bounds_iterator& operator-=(difference_type n) _NOEXCEPT + bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const bounds_iterator& rhs) const _NOEXCEPT + difference_type operator-(const bounds_iterator& rhs) const noexcept { return curr[0] - rhs.curr[0]; } - reference operator[](difference_type n) const _NOEXCEPT + reference operator[](difference_type n) const noexcept { return curr + n; } - bool operator==(const bounds_iterator& rhs) const _NOEXCEPT + bool operator==(const bounds_iterator& rhs) const noexcept { return curr == rhs.curr; } - bool operator!=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const bounds_iterator& rhs) const _NOEXCEPT + bool operator<(const bounds_iterator& rhs) const noexcept { return curr[0] < rhs.curr[0]; } - bool operator<=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const bounds_iterator& rhs) const _NOEXCEPT + bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const bounds_iterator& rhs) const _NOEXCEPT + bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(bounds_iterator& rhs) _NOEXCEPT + void swap(bounds_iterator& rhs) noexcept { std::swap(curr, rhs.curr); } @@ -1311,7 +1311,7 @@ private: }; template -bounds_iterator operator+(typename bounds_iterator::difference_type n, const bounds_iterator& rhs) _NOEXCEPT +bounds_iterator operator+(typename bounds_iterator::difference_type n, const bounds_iterator& rhs) noexcept { return rhs + n; } @@ -1322,14 +1322,14 @@ bounds_iterator operator+(typename bounds_iterator::differ namespace details { template - constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) noexcept { return bnd.strides(); } // Make a stride vector from bounds, assuming contiguous memory. template - constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) _NOEXCEPT + constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) noexcept { auto extents = bnd.index_bounds(); typename Bounds::index_type stride; @@ -1379,17 +1379,17 @@ private: bounds_type m_bounds; public: - constexpr bounds_type bounds() const _NOEXCEPT + constexpr bounds_type bounds() const noexcept { return m_bounds; } template - constexpr size_type extent() const _NOEXCEPT + constexpr size_type extent() const noexcept { static_assert(Dim < rank, "dimension should be less than rank (dimension count starts from 0)"); return m_bounds.template extent(); } - constexpr size_type size() const _NOEXCEPT + constexpr size_type size() const noexcept { return m_bounds.size(); } @@ -1397,7 +1397,7 @@ public: { return m_pdata[m_bounds.linearize(idx)]; } - constexpr pointer data() const _NOEXCEPT + constexpr pointer data() const noexcept { return m_pdata; } @@ -1411,7 +1411,7 @@ public: return Ret {m_pdata + ridx, m_bounds.slice()}; } - constexpr operator bool () const _NOEXCEPT + constexpr operator bool () const noexcept { return m_pdata != nullptr; } @@ -1451,38 +1451,38 @@ public: } template , std::remove_cv_t>::value>> - constexpr bool operator== (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator== (const basic_array_view & other) const noexcept { return m_bounds.size() == other.m_bounds.size() && (m_pdata == other.m_pdata || std::equal(this->begin(), this->end(), other.begin())); } template , std::remove_cv_t>::value>> - constexpr bool operator!= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator!= (const basic_array_view & other) const noexcept { return !(*this == other); } template , std::remove_cv_t>::value>> - constexpr bool operator< (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator< (const basic_array_view & other) const noexcept { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } template , std::remove_cv_t>::value>> - constexpr bool operator<= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator<= (const basic_array_view & other) const noexcept { return !(other < *this); } template , std::remove_cv_t>::value>> - constexpr bool operator> (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator> (const basic_array_view & other) const noexcept { return (other < *this); } template , std::remove_cv_t>::value>> - constexpr bool operator>= (const basic_array_view & other) const _NOEXCEPT + constexpr bool operator>= (const basic_array_view & other) const noexcept { return !(*this < other); } @@ -1491,20 +1491,20 @@ public: template ::value && std::is_convertible::value>> - constexpr basic_array_view(const basic_array_view & other ) _NOEXCEPT + constexpr basic_array_view(const basic_array_view & other ) noexcept : m_pdata(other.m_pdata), m_bounds(other.m_bounds) { } protected: - constexpr basic_array_view(pointer data, bounds_type bound) _NOEXCEPT + constexpr basic_array_view(pointer data, bounds_type bound) noexcept : m_pdata(data) , m_bounds(std::move(bound)) { fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0); } template - constexpr basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) _NOEXCEPT + constexpr basic_array_view(T *data, std::enable_if_t>::value, bounds_type> bound) noexcept : m_pdata(reinterpret_cast(data)) , m_bounds(std::move(bound)) { @@ -1759,7 +1759,7 @@ public: // to bytes array template ::value_type>>::value> - constexpr auto as_bytes() const _NOEXCEPT -> + constexpr auto as_bytes() const noexcept -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1767,7 +1767,7 @@ public: } template ::value_type>>::value> - constexpr auto as_writeable_bytes() const _NOEXCEPT -> + constexpr auto as_writeable_bytes() const noexcept -> array_view, static_cast(details::StaticSizeHelper::value)> { static_assert(Enabled, "The value_type of array_view must be standarded layout"); @@ -1777,7 +1777,7 @@ public: // from bytes array template::value, typename Dummy = std::enable_if_t> - constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const noexcept -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0), "Target type must be standard layout and its size must match the byte array size"); @@ -1786,7 +1786,7 @@ public: } template::value, typename Dummy = std::enable_if_t> - constexpr auto as_array_view() const _NOEXCEPT -> array_view(dynamic_range))> + constexpr auto as_array_view() const noexcept -> array_view(dynamic_range))> { static_assert(std::is_standard_layout::value && (Base::bounds_type::static_size == dynamic_range || Base::bounds_type::static_size % sizeof(U) == 0), "Target type must be standard layout and its size must match the byte array size"); @@ -1796,61 +1796,61 @@ public: // section on linear space template - constexpr array_view first() const _NOEXCEPT + constexpr array_view first() const noexcept { static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); // ensures we only check condition when needed return { this->data(), Count }; } - constexpr array_view first(size_type count) const _NOEXCEPT + constexpr array_view first(size_type count) const noexcept { fail_fast_assert(count <= this->size()); return { this->data(), count }; } template - constexpr array_view last() const _NOEXCEPT + constexpr array_view last() const noexcept { static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); return { this->data() + this->size() - Count, Count }; } - constexpr array_view last(size_type count) const _NOEXCEPT + constexpr array_view last(size_type count) const noexcept { fail_fast_assert(count <= this->size()); return { this->data() + this->size() - count, count }; } template - constexpr array_view sub() const _NOEXCEPT + constexpr array_view sub() const noexcept { static_assert(bounds_type::static_size == dynamic_range || ((Offset == 0 || Offset <= bounds_type::static_size) && Offset + Count <= bounds_type::static_size), "Index is out of bound"); fail_fast_assert(bounds_type::static_size != dynamic_range || ((Offset == 0 || Offset <= this->size()) && Offset + Count <= this->size())); return { this->data() + Offset, Count }; } - constexpr array_view sub(size_type offset, size_type count = dynamic_range) const _NOEXCEPT + constexpr array_view sub(size_type offset, size_type count = dynamic_range) const noexcept { fail_fast_assert((offset == 0 || offset <= this->size()) && (count == dynamic_range || (offset + count) <= this->size())); return { this->data() + offset, count == dynamic_range ? this->length() - offset : count }; } // size - constexpr size_type length() const _NOEXCEPT + constexpr size_type length() const noexcept { return this->size(); } - constexpr size_type used_length() const _NOEXCEPT + constexpr size_type used_length() const noexcept { return length(); } - constexpr size_type bytes() const _NOEXCEPT + constexpr size_type bytes() const noexcept { return sizeof(value_type) * this->size(); } - constexpr size_type used_bytes() const _NOEXCEPT + constexpr size_type used_bytes() const noexcept { return bytes(); } @@ -2064,93 +2064,93 @@ private: contiguous_array_view_iterator (const ArrayView *container, bool isbegin = false) : m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) { } public: - reference operator*() const _NOEXCEPT + reference operator*() const noexcept { validateThis(); return *m_pdata; } - pointer operator->() const _NOEXCEPT + pointer operator->() const noexcept { validateThis(); return m_pdata; } - contiguous_array_view_iterator& operator++() _NOEXCEPT + contiguous_array_view_iterator& operator++() noexcept { ++m_pdata; return *this; } - contiguous_array_view_iterator operator++(int)_NOEXCEPT + contiguous_array_view_iterator operator++(int)noexcept { auto ret = *this; ++(*this); return ret; } - contiguous_array_view_iterator& operator--() _NOEXCEPT + contiguous_array_view_iterator& operator--() noexcept { --m_pdata; return *this; } - contiguous_array_view_iterator operator--(int)_NOEXCEPT + contiguous_array_view_iterator operator--(int)noexcept { auto ret = *this; --(*this); return ret; } - contiguous_array_view_iterator operator+(difference_type n) const _NOEXCEPT + contiguous_array_view_iterator operator+(difference_type n) const noexcept { contiguous_array_view_iterator ret{ *this }; return ret += n; } - contiguous_array_view_iterator& operator+=(difference_type n) _NOEXCEPT + contiguous_array_view_iterator& operator+=(difference_type n) noexcept { m_pdata += n; return *this; } - contiguous_array_view_iterator operator-(difference_type n) const _NOEXCEPT + contiguous_array_view_iterator operator-(difference_type n) const noexcept { contiguous_array_view_iterator ret{ *this }; return ret -= n; } - contiguous_array_view_iterator& operator-=(difference_type n) _NOEXCEPT + contiguous_array_view_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + difference_type operator-(const contiguous_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_validator == rhs.m_validator); return m_pdata - rhs.m_pdata; } - reference operator[](difference_type n) const _NOEXCEPT + reference operator[](difference_type n) const noexcept { return *(*this + n); } - bool operator==(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator==(const contiguous_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_validator == rhs.m_validator); return m_pdata == rhs.m_pdata; } - bool operator!=(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator!=(const contiguous_array_view_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator<(const contiguous_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_validator == rhs.m_validator); return m_pdata < rhs.m_pdata; } - bool operator<=(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator<=(const contiguous_array_view_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator>(const contiguous_array_view_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const contiguous_array_view_iterator& rhs) const _NOEXCEPT + bool operator>=(const contiguous_array_view_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(contiguous_array_view_iterator& rhs) _NOEXCEPT + void swap(contiguous_array_view_iterator& rhs) noexcept { std::swap(m_pdata, rhs.m_pdata); std::swap(m_validator, rhs.m_validator); @@ -2158,7 +2158,7 @@ public: }; template -contiguous_array_view_iterator operator+(typename contiguous_array_view_iterator::difference_type n, const contiguous_array_view_iterator& rhs) _NOEXCEPT +contiguous_array_view_iterator operator+(typename contiguous_array_view_iterator::difference_type n, const contiguous_array_view_iterator& rhs) noexcept { return rhs + n; } @@ -2182,91 +2182,91 @@ private: { } public: - reference operator*() const _NOEXCEPT + reference operator*() const noexcept { return (*m_container)[*m_itr]; } - pointer operator->() const _NOEXCEPT + pointer operator->() const noexcept { return &(*m_container)[*m_itr]; } - general_array_view_iterator& operator++() _NOEXCEPT + general_array_view_iterator& operator++() noexcept { ++m_itr; return *this; } - general_array_view_iterator operator++(int)_NOEXCEPT + general_array_view_iterator operator++(int)noexcept { auto ret = *this; ++(*this); return ret; } - general_array_view_iterator& operator--() _NOEXCEPT + general_array_view_iterator& operator--() noexcept { --m_itr; return *this; } - general_array_view_iterator operator--(int)_NOEXCEPT + general_array_view_iterator operator--(int)noexcept { auto ret = *this; --(*this); return ret; } - general_array_view_iterator operator+(difference_type n) const _NOEXCEPT + general_array_view_iterator operator+(difference_type n) const noexcept { general_array_view_iterator ret{ *this }; return ret += n; } - general_array_view_iterator& operator+=(difference_type n) _NOEXCEPT + general_array_view_iterator& operator+=(difference_type n) noexcept { m_itr += n; return *this; } - general_array_view_iterator operator-(difference_type n) const _NOEXCEPT + general_array_view_iterator operator-(difference_type n) const noexcept { general_array_view_iterator ret{ *this }; return ret -= n; } - general_array_view_iterator& operator-=(difference_type n) _NOEXCEPT + general_array_view_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const general_array_view_iterator& rhs) const _NOEXCEPT + difference_type operator-(const general_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_container == rhs.m_container); return m_itr - rhs.m_itr; } - value_type operator[](difference_type n) const _NOEXCEPT + value_type operator[](difference_type n) const noexcept { return (*m_container)[m_itr[n]];; } - bool operator==(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator==(const general_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_container == rhs.m_container); return m_itr == rhs.m_itr; } - bool operator !=(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator !=(const general_array_view_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator<(const general_array_view_iterator& rhs) const noexcept { fail_fast_assert(m_container == rhs.m_container); return m_itr < rhs.m_itr; } - bool operator<=(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator<=(const general_array_view_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator>(const general_array_view_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const general_array_view_iterator& rhs) const _NOEXCEPT + bool operator>=(const general_array_view_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(general_array_view_iterator& rhs) _NOEXCEPT + void swap(general_array_view_iterator& rhs) noexcept { std::swap(m_itr, rhs.m_itr); std::swap(m_container, rhs.m_container); @@ -2274,22 +2274,32 @@ public: }; template -general_array_view_iterator operator+(typename general_array_view_iterator::difference_type n, const general_array_view_iterator& rhs) _NOEXCEPT +general_array_view_iterator operator+(typename general_array_view_iterator::difference_type n, const general_array_view_iterator& rhs) noexcept { return rhs + n; } } // namespace gsl -#if defined(_MSC_VER) +#ifdef _MSC_VER + #undef constexpr #pragma pop_macro("constexpr") -#endif -#if defined(_MSC_VER) && _MSC_VER <= 1800 +#if _MSC_VER <= 1800 #pragma warning(pop) + +#ifndef GSL_THROWS_FOR_TESTING +#pragma undef noexcept +#endif // GSL_THROWS_FOR_TESTING + #endif // _MSC_VER <= 1800 -#pragma pop_macro("_NOEXCEPT") +#endif // _MSC_VER + +#if defined(GSL_THROWS_FOR_TESTING) +#undef noexcept +#endif // GSL_THROWS_FOR_TESTING + #endif // GSL_ARRAY_VIEW_H diff --git a/include/gsl.h b/include/gsl.h index e15ca5c..dd3d971 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -23,6 +23,34 @@ #include "string_view.h" // zstring, string_view, zstring_builder... #include +#ifdef _MSC_VER + +// No MSVC does constexpr fully yet +#pragma push_macro("constexpr") +#define constexpr /* nothing */ + +// MSVC 2013 workarounds +#if _MSC_VER <= 1800 + +// noexcept is not understood +#ifndef GSL_THROWS_FOR_TESTING +#define noexcept /* nothing */ +#endif + +// turn off some misguided warnings +#pragma warning(push) +#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior + +#endif // _MSC_VER <= 1800 + +#endif // _MSC_VER + +// In order to test the library, we need it to throw exceptions that we can catch +#ifdef GSL_THROWS_FOR_TESTING +#define noexcept /* nothing */ +#endif // GSL_THROWS_FOR_TESTING + + namespace gsl { @@ -356,4 +384,24 @@ template using maybe_null = maybe_null_ret; } // namespace gsl +#ifdef _MSC_VER + +#undef constexpr +#pragma pop_macro("constexpr") + +#if _MSC_VER <= 1800 +#pragma warning(pop) + +#ifndef GSL_THROWS_FOR_TESTING +#pragma undef noexcept +#endif // GSL_THROWS_FOR_TESTING + +#endif // _MSC_VER <= 1800 + +#endif // _MSC_VER + +#if defined(GSL_THROWS_FOR_TESTING) +#undef noexcept +#endif // GSL_THROWS_FOR_TESTING + #endif // GSL_GSL_H From dd923eee5f02dd7bae935dfa95da570e29c50c51 Mon Sep 17 00:00:00 2001 From: Seth Cantrell Date: Thu, 1 Oct 2015 20:53:37 -0400 Subject: [PATCH 39/59] Add column limit to .clang-format --- .clang-format | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index bef7ebc..b80d2c6 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,4 @@ -ColumnLimit: 0 +ColumnLimit: 100 UseTab: Never IndentWidth: 4 @@ -6,7 +6,7 @@ AccessModifierOffset: -4 NamespaceIndentation: Inner BreakBeforeBraces: Allman -AlwaysBreakTemplateDeclarations: false +AlwaysBreakTemplateDeclarations: true BreakConstructorInitializersBeforeComma: true ConstructorInitializerAllOnOneLineOrOnePerLine: true AllowShortBlocksOnASingleLine: true From b8ec73a1790fb682037d6f5ca7109e7d5dfddb06 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Fri, 2 Oct 2015 15:58:23 -0700 Subject: [PATCH 40/59] Fix moving a final_act twice --- include/gsl.h | 2 +- tests/utils_tests.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index dd3d971..824ca6a 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -80,7 +80,7 @@ class final_act public: explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {} - final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } + final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_) { other.invoke_ = false; } final_act(const final_act&) = delete; final_act& operator=(const final_act&) = delete; diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 3090c7d..9406e6b 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -44,9 +44,14 @@ SUITE(utils_tests) auto _1 = finally([&]() {f(i);}); { auto _2 = std::move(_1); - CHECK(i == 0); + CHECK(i == 0); } - CHECK(i == 1); + CHECK(i == 1); + { + auto _2 = std::move(_1); + CHECK(i == 1); + } + CHECK(i == 1); } CHECK(i == 1); } From 144ee44132d920ac8d8189c32ad07853119cd2e4 Mon Sep 17 00:00:00 2001 From: kkoenig Date: Sat, 3 Oct 2015 22:02:49 -0700 Subject: [PATCH 41/59] First arg of vector ctor should be num elements, second should be value. Fixes issue #121 --- tests/string_view_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/string_view_tests.cpp b/tests/string_view_tests.cpp index 84b7f3f..fb57845 100644 --- a/tests/string_view_tests.cpp +++ b/tests/string_view_tests.cpp @@ -45,7 +45,7 @@ SUITE(string_view_tests) TEST(TestConstructFromStdVector) { - std::vector vec('h', 5); + std::vector vec(5, 'h'); string_view<> v = vec; CHECK(v.length() == vec.size()); } From fda8e1231008bdee8f5356a241ae9fd4ffc19872 Mon Sep 17 00:00:00 2001 From: Treb Connell Date: Mon, 5 Oct 2015 13:34:50 -0700 Subject: [PATCH 42/59] Fix #124 remove maybe_null --- include/gsl.h | 187 ----------------------- tests/CMakeLists.txt | 1 - tests/maybenull_tests.cpp | 304 -------------------------------------- 3 files changed, 492 deletions(-) delete mode 100644 tests/maybenull_tests.cpp diff --git a/include/gsl.h b/include/gsl.h index 824ca6a..519682b 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -195,193 +195,6 @@ private: not_null& operator-=(size_t) = delete; }; - -// -// maybe_null -// -// Describes an optional pointer - provides symmetry with not_null -// -template -class maybe_null_ret; - -template -class maybe_null_dbg -{ - template - friend class maybe_null_dbg; - - static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); -public: - maybe_null_dbg() : ptr_(nullptr), tested_(false) {} - maybe_null_dbg(std::nullptr_t) : ptr_(nullptr), tested_(false) {} - - maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {} - maybe_null_dbg& operator=(const T& p) - { - if (ptr_ != p) - { - ptr_ = p; - tested_ = false; - } - return *this; - } - - - maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {} - maybe_null_dbg& operator=(const maybe_null_dbg& rhs) - { - if (this != &rhs) - { - ptr_ = rhs.ptr_; - tested_ = false; - } - return *this; - } - - - template ::value>> - maybe_null_dbg(const not_null &other) : ptr_(other.get()), tested_(false) {} - - template ::value>> - maybe_null_dbg& operator=(const not_null &other) - { - ptr_ = other.get(); - tested_ = false; - return *this; - } - - - template ::value>> - maybe_null_dbg(const maybe_null_dbg &other) : ptr_(other.ptr_), tested_(false) {} - - template ::value>> - maybe_null_dbg& operator=(const maybe_null_dbg &other) - { - ptr_ = other.ptr_; - tested_ = false; - return *this; - } - - - template ::value>> - maybe_null_dbg(const maybe_null_ret &other) : ptr_(other.get()), tested_(false) {} - - template ::value>> - maybe_null_dbg& operator=(const maybe_null_ret &other) - { - ptr_ = other.get(); - tested_ = false; - return *this; - } - - - bool present() const { tested_ = true; return ptr_ != nullptr; } - - bool operator==(const T& rhs) const { tested_ = true; return ptr_ == rhs; } - bool operator!=(const T& rhs) const { return !(*this == rhs); } - template ::value>> - bool operator==(const maybe_null_dbg& rhs) const { tested_ = true; rhs.tested_ = true; return ptr_ == rhs.ptr_; } - template ::value>> - bool operator!=(const maybe_null_dbg& rhs) const { return !(*this == rhs); } - - T get() const { - fail_fast_assert(tested_); -#ifdef _MSC_VER - __assume(ptr_ != nullptr); -#endif - return ptr_; - } - - operator T() const { return get(); } - T operator->() const { return get(); } - -private: - // unwanted operators...pointers only point to single objects! - // TODO ensure all arithmetic ops on this type are unavailable - maybe_null_dbg& operator++() = delete; - maybe_null_dbg& operator--() = delete; - maybe_null_dbg operator++(int) = delete; - maybe_null_dbg operator--(int) = delete; - maybe_null_dbg& operator+(size_t) = delete; - maybe_null_dbg& operator+=(size_t) = delete; - maybe_null_dbg& operator-(size_t) = delete; - maybe_null_dbg& operator-=(size_t) = delete; - - T ptr_; - mutable bool tested_; -}; - -template -class maybe_null_ret -{ - static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); -public: - maybe_null_ret() : ptr_(nullptr) {} - maybe_null_ret(std::nullptr_t) : ptr_(nullptr) {} - - maybe_null_ret(const T& p) : ptr_(p) {} - maybe_null_ret& operator=(const T& p) { ptr_ = p; return *this; } - - maybe_null_ret(const maybe_null_ret& rhs) = default; - maybe_null_ret& operator=(const maybe_null_ret& rhs) = default; - - template ::value>> - maybe_null_ret(const not_null &other) : ptr_(other.get()) {} - - template ::value>> - maybe_null_ret& operator=(const not_null &other) - { - ptr_ = other.get(); - return *this; - } - - - template ::value>> - maybe_null_ret(const maybe_null_ret &other) : ptr_(other.get()) {} - - template ::value>> - maybe_null_ret& operator=(const maybe_null_ret &other) - { - ptr_ = other.get(); - return *this; - } - - - template ::value>> - maybe_null_ret(const maybe_null_dbg &other) : ptr_(other.get()) {} - - template ::value>> - maybe_null_ret& operator=(const maybe_null_dbg &other) - { - ptr_ = other.get(); - return *this; - } - - - bool present() const { return ptr_ != nullptr; } - - T get() const { return ptr_; } - - operator T() const { return get(); } - T operator->() const { return get(); } - -private: - // unwanted operators...pointers only point to single objects! - // TODO ensure all arithmetic ops on this type are unavailable - maybe_null_ret& operator++() = delete; - maybe_null_ret& operator--() = delete; - maybe_null_ret operator++(int) = delete; - maybe_null_ret operator--(int) = delete; - maybe_null_ret& operator+(size_t) = delete; - maybe_null_ret& operator+=(size_t) = delete; - maybe_null_ret& operator-(size_t) = delete; - maybe_null_ret& operator-=(size_t) = delete; - - T ptr_; -}; - -template using maybe_null = maybe_null_ret; - } // namespace gsl #ifdef _MSC_VER diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 774413f..5e4c395 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,7 +47,6 @@ add_gsl_test(array_view_tests) add_gsl_test(string_view_tests) add_gsl_test(at_tests) add_gsl_test(bounds_tests) -add_gsl_test(maybenull_tests) add_gsl_test(notnull_tests) add_gsl_test(assertion_tests) add_gsl_test(utils_tests) diff --git a/tests/maybenull_tests.cpp b/tests/maybenull_tests.cpp deleted file mode 100644 index 74d449f..0000000 --- a/tests/maybenull_tests.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include - -using namespace gsl; - -struct MyBase { bool foo() { return true; } }; -struct MyDerived : public MyBase {}; -struct Unrelated {}; - -SUITE(MaybeNullTests) -{ - TEST(TestMaybeNull1) - { -#ifdef CONFIRM_COMPILATION_ERRORS - // Forbid non-nullptr assignable types - maybe_null_ret> f_ret(std::vector{1}); - maybe_null_ret> f_ret(std::vector{1}); - maybe_null_ret z_ret(10); - maybe_null_dbg> y_dbg({1,2}); - maybe_null_dbg z_dbg(10); - maybe_null_dbg> y_dbg({1,2}); -#endif - int n = 5; - maybe_null_dbg opt_n(&n); - int result = 0; - bool threw = false; - - CHECK_THROW(result = *opt_n, fail_fast); - - maybe_null_ret> x_ret(std::make_shared(10)); // shared_ptr is nullptr assignable - maybe_null_dbg> x_dbg(std::make_shared(10)); // shared_ptr is nullptr assignable - } - - TEST(TestMaybeNull2) - { - int n = 5; - maybe_null opt_n(&n); - int result = 0; - if (opt_n.present()) - result = *opt_n; - } - - TEST(TestMaybeNull3) - { - int n = 5; - maybe_null opt_n(&n); - int result = 0; - if (opt_n != nullptr) - result = *opt_n; - } - - int test4_helper(maybe_null p) - { - if (p != nullptr) - return *p; - return -1; - } - - TEST(TestMaybeNull4) - { - int n = 5; - int result = 0; - result = test4_helper(&n); - } - - int test5_helper(maybe_null_dbg p) - { - return *p; - } - - TEST(TestMaybeNull5) - { - int n = 5; - int result = 0; - bool threw = false; - - CHECK_THROW(result = test5_helper(&n), fail_fast); - } - -#ifdef CONFIRM_COMPILATION_ERRORS - int TestMaybeNull6() - { - int n; - maybe_null o(n); - } -#endif - - int g_int; - void test7_helper(maybe_null *> outptr) - { - g_int = 5; - - if (outptr.present()) - *outptr = &g_int; - } - - void test7b_helper(maybe_null_dbg *> outptr) - { - g_int = 5; - - if (outptr.present()) - *outptr = &g_int; - } - - TEST(TestMaybeNull7a) - { - maybe_null outval; - test7_helper(&outval); - CHECK(outval.present() && *outval == 5); - } - - TEST(TestMaybeNull7b) - { - maybe_null_dbg outval; - test7b_helper(&outval); - CHECK_THROW((void)*outval, fail_fast); - } - - int test8_helper1(maybe_null_dbg opt) - { - return *opt; - } - - int test8_helper2a(maybe_null_dbg opt) - { - if (!opt.present()) - return 0; - return test8_helper1(opt); - } - - TEST(TestMaybeNull8a) - { - int n = 5; - maybe_null_dbg opt(&n); - CHECK_THROW(test8_helper2a(opt), fail_fast); - } - -#ifdef CONVERT_TO_PTR_TO_CONST - int test9_helper(maybe_null copt) - { - if (copt.present()) - return *copt; - return 0; - } - - void TestMaybeNull9() - { - int n = 5; - maybe_null opt(&n); - CHECK_THROW(test9_helper(opt), fail_fast); - } -#endif - - TEST(TestMaybeNullCasting) - { - MyDerived derived; - maybe_null p = &derived; - CHECK(p.present()); - - maybe_null q = p; - CHECK(q == p); - - maybe_null_dbg pdbg = &derived; - CHECK(pdbg.present()); - - maybe_null_dbg qdbg = pdbg; - CHECK(qdbg == pdbg); - -#ifdef CONFIRM_COMPILATION_ERRORS - maybe_null r = p; - maybe_null s = reinterpret_cast(p); -#endif - maybe_null_dbg t = reinterpret_cast(p.get()); - - CHECK_THROW((void)(void*)t.get(), fail_fast); - maybe_null_dbg u = reinterpret_cast(p.get()); - CHECK(u.present()); - CHECK((void*)p.get() == (void*)u.get()); - } - - TEST(TestMaybeNullArrow) - { - MyDerived derived; - maybe_null_dbg p = &derived; - - CHECK_THROW(p->foo(), fail_fast); - CHECK(p.present()); - CHECK(p->foo()); - - maybe_null q = p; - CHECK(q.present()); - CHECK(q->foo()); - } - - TEST(TestMaybeNullCompare) - { - int i1 = 1; - int i2 = 2; - - maybe_null_dbg p1 = &i1; - maybe_null_dbg p1_2 = &i1; - maybe_null_dbg p2 = &i2; - - CHECK_THROW(p1.get(), fail_fast); - CHECK_THROW(p1_2.get(), fail_fast); - CHECK_THROW(p2.get(), fail_fast); - - CHECK(p1 != p2); - CHECK(!(p1 == p2)); - CHECK(p1 == p1); - CHECK(p1 == p1_2); - - // Make sure we no longer throw here - CHECK(p1.get() != nullptr); - CHECK(p1_2.get() != nullptr); - CHECK(p2.get() != nullptr); - } - - TEST(TestMaybeNullCopy) - { - int i1 = 1; - int i2 = 2; - - maybe_null_dbg p1 = &i1; - maybe_null_dbg p1_2 = &i1; - maybe_null_dbg p2 = &i2; - - CHECK(p1 != p2); - CHECK(p1 == p1_2); - - // Make sure we no longer throw here - CHECK(p1.get() != nullptr); - CHECK(p2.get() != nullptr); - - p1 = p2; - - // Make sure we now throw - CHECK_THROW(p1.get(), fail_fast); - - CHECK(p1 == p2); - CHECK(p1 != p1_2); - - // Make sure we no longer throw here - CHECK(p1.get() != nullptr); - } - - TEST(TestMaybeNullAssignmentOps) - { - MyBase base; - MyDerived derived; - Unrelated unrelated; - - not_null nnBase(&base); - not_null nnDerived(&derived); - not_null nnUnrelated(&unrelated); - - maybe_null_ret mnBase_ret1(&base), mnBase_ret2; - mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret - mnBase_ret2 = nnBase; // maybe_null_ret = not_null - - maybe_null_ret mnDerived_ret(&derived); - mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret - mnBase_ret1 = &derived; // maybe_null_ret = U; - mnBase_ret1 = nnDerived; // maybe_null_ret = not_null - - maybe_null_ret mnUnrelated_ret; - mnUnrelated_ret = &unrelated; // maybe_null_ret = T - - maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; - mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg - mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null - - maybe_null_dbg mnDerived_dbg(&derived); - mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg - mnBase_dbg1 = &derived; // maybe_null_dbg = U; - mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null - - maybe_null_dbg mnUnrelated_dbg; - mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T - } -} - -int main(int, const char *[]) -{ - return UnitTest::RunAllTests(); -} From db38497d05887e8c901504fa09d71042ed8bb3c0 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 5 Oct 2015 12:34:23 -0700 Subject: [PATCH 43/59] Removed coordinate_facade class --- include/array_view.h | 499 ++++++++++++++++--------------------- tests/array_view_tests.cpp | 23 +- 2 files changed, 224 insertions(+), 298 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 046cbf8..aa1b4e5 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -73,180 +73,6 @@ namespace details static const size_t max_value = std::is_signed::value ? static_cast::type>(-1) / 2 : static_cast(-1); }; - - template - class coordinate_facade - { - static_assert(std::is_integral::value - && sizeof(ValueType) <= sizeof(size_t), "ValueType must be an integral type!"); - static_assert(Rank > 0, "Rank must be greater than 0!"); - - template - friend class coordinate_facade; - public: - using reference = ValueType&; - using const_reference = const ValueType&; - using value_type = ValueType; - static const size_t rank = Rank; - constexpr coordinate_facade() noexcept - { - static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - } - constexpr coordinate_facade(const value_type(&values)[rank]) noexcept - { - static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - for (size_t i = 0; i < rank; ++i) - elems[i] = values[i]; - } - constexpr coordinate_facade(value_type e0) noexcept - { - static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - static_assert(rank == 1, "This constructor can only be used with rank == 1."); - elems[0] = e0; - } - // Preconditions: il.size() == rank - constexpr coordinate_facade(std::initializer_list il) - { - static_assert(std::is_base_of::value, "ConcreteType must be derived from coordinate_facade."); - fail_fast_assert(il.size() == rank, "The size of the initializer list must match the rank of the array"); - for (size_t i = 0; i < rank; ++i) - { - elems[i] = begin(il)[i]; - } - } - - constexpr coordinate_facade(const coordinate_facade & other) = default; - - template - constexpr coordinate_facade(const coordinate_facade & other) - { - for (size_t i = 0; i < rank; ++i) - { - fail_fast_assert(static_cast(other.elems[i]) <= SizeTypeTraits::max_value); - elems[i] = static_cast(other.elems[i]); - } - } - protected: - coordinate_facade& operator=(const coordinate_facade& rhs) = default; - // Preconditions: component_idx < rank - constexpr reference operator[](size_t component_idx) - { - fail_fast_assert(component_idx < rank, "Component index must be less than rank"); - return elems[component_idx]; - } - // Preconditions: component_idx < rank - constexpr const_reference operator[](size_t component_idx) const - { - fail_fast_assert(component_idx < rank, "Component index must be less than rank"); - return elems[component_idx]; - } - constexpr bool operator==(const ConcreteType& rhs) const noexcept - { - return std::equal(elems, elems + rank, rhs.elems); - } - constexpr bool operator!=(const ConcreteType& rhs) const noexcept - { - return !(to_concrete() == rhs); - } - constexpr ConcreteType operator+() const noexcept - { - return to_concrete(); - } - constexpr ConcreteType operator-() const - { - ConcreteType ret = to_concrete(); - std::transform(ret, ret + rank, ret, std::negate{}); - return ret; - } - constexpr ConcreteType operator+(const ConcreteType& rhs) const - { - ConcreteType ret = to_concrete(); - ret += rhs; - return ret; - } - constexpr ConcreteType operator-(const ConcreteType& rhs) const - { - ConcreteType ret = to_concrete(); - ret -= rhs; - return ret; - } - constexpr ConcreteType& operator+=(const ConcreteType& rhs) - { - for (size_t i = 0; i < rank; ++i) - elems[i] += rhs.elems[i]; - return to_concrete(); - } - constexpr ConcreteType& operator-=(const ConcreteType& rhs) - { - for (size_t i = 0; i < rank; ++i) - elems[i] -= rhs.elems[i]; - return to_concrete(); - } - constexpr ConcreteType& operator++() - { - static_assert(rank == 1, "This operator can only be used with rank == 1."); - ++elems[0]; - return to_concrete(); - } - constexpr ConcreteType operator++(int) - { - static_assert(rank == 1, "This operator can only be used with rank == 1."); - ConcreteType ret = to_concrete(); - ++(*this); - return ret; - } - constexpr ConcreteType& operator--() - { - static_assert(rank == 1, "This operator can only be used with rank == 1."); - --elems[0]; - return to_concrete(); - } - constexpr ConcreteType operator--(int) - { - static_assert(rank == 1, "This operator can only be used with rank == 1."); - ConcreteType ret = to_concrete(); - --(*this); - return ret; - } - constexpr ConcreteType operator*(value_type v) const - { - ConcreteType ret = to_concrete(); - ret *= v; - return ret; - } - constexpr ConcreteType operator/(value_type v) const - { - ConcreteType ret = to_concrete(); - ret /= v; - return ret; - } - friend constexpr ConcreteType operator*(value_type v, const ConcreteType& rhs) - { - return rhs * v; - } - constexpr ConcreteType& operator*=(value_type v) - { - for (size_t i = 0; i < rank; ++i) - elems[i] *= v; - return to_concrete(); - } - constexpr ConcreteType& operator/=(value_type v) - { - for (size_t i = 0; i < rank; ++i) - elems[i] /= v; - return to_concrete(); - } - value_type elems[rank] = {}; - private: - constexpr const ConcreteType& to_concrete() const noexcept - { - return static_cast(*this); - } - constexpr ConcreteType& to_concrete() noexcept - { - return static_cast(*this); - } - }; template class arrow_proxy { @@ -268,47 +94,160 @@ namespace details } template -class index : private details::coordinate_facade, ValueType, Rank> +class index final { - using Base = details::coordinate_facade, ValueType, Rank>; - friend Base; + static_assert(std::is_integral::value, "ValueType must be an integral type!"); + static_assert(Rank > 0, "Rank must be greater than 0!"); + template friend class index; + public: - using Base::rank; - using reference = typename Base::reference; - using const_reference = typename Base::const_reference; - using size_type = typename Base::value_type; - using value_type = typename Base::value_type; - constexpr index() noexcept : Base(){} - constexpr index(const value_type (&values)[rank]) noexcept : Base(values) {} - constexpr index(std::initializer_list il) : Base(il) {} + static const size_t rank = Rank; + using value_type = std::remove_reference_t; + using reference = std::add_lvalue_reference_t; + using const_reference = std::add_lvalue_reference_t>; - constexpr index(const index &) = default; - - template - constexpr index(const index &other) : Base(other) + constexpr index(const value_type(&values)[Rank]) noexcept { - } - constexpr static index shift_left(const index& other) noexcept - { - value_type (&arr)[rank] = (value_type(&)[rank])(*(other.elems + 1)); - return index(arr); + std::copy(values, values + Rank, elems); } - using Base::operator[]; - using Base::operator==; - using Base::operator!=; - using Base::operator+; - using Base::operator-; - using Base::operator+=; - using Base::operator-=; - using Base::operator++; - using Base::operator--; - using Base::operator*; - using Base::operator/; - using Base::operator*=; - using Base::operator/=; + // Preconditions: il.size() == rank + constexpr index(std::initializer_list il) noexcept + { + fail_fast_assert(il.size() == Rank, "The size of the initializer list must match the rank of the array"); + std::copy(begin(il), end(il), elems); + } + + constexpr index(const index& other) noexcept = default; + + // copy from index over smaller domain + template + constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value <= details::SizeTypeTraits::max_value), const index>::type& other) noexcept + { + std::copy(other.elems, other.elems + Rank, elems); + } + + // copy from index over larger domain + template + constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value > details::SizeTypeTraits::max_value), const index>::type& other) noexcept + { + for (size_t i = 0; i < Rank; ++i) + { + fail_fast_assert(other.elems[i] <= static_cast(SizeTypeTraits::max_value)); + elems[i] = static_cast(other.elems[i]); + } + } + + constexpr static index shift_left(const index& other) noexcept + { + value_type(&arr)[Rank] = (value_type(&)[Rank])(*(other.elems + 1)); + return index(arr); + } + + constexpr static index zero() noexcept + { + value_type zero[Rank] = {}; + return index(zero); + } + + constexpr index& operator=(const index& rhs) noexcept = default; + + // Preconditions: component_idx < rank + constexpr reference operator[](size_t component_idx) + { + fail_fast_assert(component_idx < Rank, "Component index must be less than rank"); + return elems[component_idx]; + } + + // Preconditions: component_idx < rank + constexpr const_reference operator[](size_t component_idx) const noexcept + { + fail_fast_assert(component_idx < Rank, "Component index must be less than rank"); + return elems[component_idx]; + } + + constexpr bool operator==(const index& rhs) const noexcept + { + return std::equal(elems, elems + rank, rhs.elems); + } + + constexpr bool operator!=(const index& rhs) const noexcept + { + return !(this == rhs); + } + + constexpr index operator+() const noexcept + { + return *this; + } + + constexpr index operator-() const noexcept + { + index ret = *this; + std::transform(ret, ret + rank, ret, std::negate{}); + return ret; + } + + constexpr index operator+(const index& rhs) const noexcept + { + index ret = *this; + ret += rhs; + return ret; + } + + constexpr index operator-(const index& rhs) const noexcept + { + index ret = *this; + ret -= rhs; + return ret; + } + + constexpr index& operator+=(const index& rhs) noexcept + { + std::transform(elems, elems + rank, rhs.elems, elems, std::plus{}); + return *this; + } + + constexpr index& operator-=(const index& rhs) noexcept + { + std::transform(elems, elems + rank, rhs.elems, elems, std::minus{}); + return *this; + } + + constexpr index operator*(value_type v) const noexcept + { + index ret = *this; + ret *= v; + return ret; + } + + constexpr index operator/(value_type v) const noexcept + { + index ret = *this; + ret /= v; + return ret; + } + + friend static constexpr index operator*(value_type v, const index& rhs) noexcept + { + return rhs * v; + } + + constexpr index& operator*=(value_type v) noexcept + { + std::transform(elems, elems + rank, elems, [v](value_type x) { return std::multiplies{}(x, v); }); + return *this; + } + + constexpr index& operator/=(value_type v) noexcept + { + std::transform(elems, elems + rank, elems, [v](value_type x) { return std::divides{}(x, v); }); + return *this; + } +private: + value_type elems[Rank] = {}; }; template @@ -316,51 +255,60 @@ class index<1, ValueType> { template friend class index; + public: static const size_t rank = 1; - using reference = ValueType&; - using const_reference = const ValueType&; - using size_type = ValueType; - using value_type = ValueType; + using value_type = std::remove_reference_t; + using reference = std::add_lvalue_reference_t; + using const_reference = std::add_lvalue_reference_t>; - constexpr index() noexcept : value(0) - { - } constexpr index(value_type e0) noexcept : value(e0) - { - } + {} + constexpr index(const value_type(&values)[1]) noexcept : index(values[0]) - { - } + {} + // Preconditions: il.size() == rank - constexpr index(std::initializer_list il) + constexpr index(std::initializer_list il) noexcept { fail_fast_assert(il.size() == rank, "Size of the initializer list must match the rank of the array"); value = begin(il)[0]; } - constexpr index(const index &) = default; + constexpr index(const index &) noexcept = default; template - constexpr index(const index<1, OtherValueType> & other) + constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value <= details::SizeTypeTraits::max_value), const index<1, OtherValueType>>::type& other) noexcept { - fail_fast_assert(other.value <= details::SizeTypeTraits::max_value); value = static_cast(other.value); } - constexpr static index shift_left(const index& other) noexcept + template + constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value > details::SizeTypeTraits::max_value), const index<1, OtherValueType>>::type& other) noexcept + { + fail_fast_assert(other.value <= static_cast(SizeTypeTraits::max_value)); + value = static_cast(other.value); + } + + constexpr static index shift_left(const index<2, value_type>& other) noexcept { return other.elems[1]; } - // Preconditions: component_idx < rank - constexpr reference operator[](size_type component_idx) noexcept + + constexpr static index zero() noexcept + { + return 0; + } + + // Preconditions: component_idx < 1 + constexpr reference operator[](value_type component_idx) noexcept { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); return value; } - // Preconditions: component_idx < rank - constexpr const_reference operator[](size_type component_idx) const noexcept + // Preconditions: component_idx < 1 + constexpr const_reference operator[](value_type component_idx) const noexcept { fail_fast_assert(component_idx == 0, "Component index must be less than rank"); (void)(component_idx); @@ -440,9 +388,9 @@ public: value /= v; return *this; } - friend constexpr index operator*(value_type v, const index& rhs) noexcept + friend static constexpr index operator*(value_type v, const index& rhs) noexcept { - return index(rhs * v); + return{ rhs * v }; } private: value_type value; @@ -855,9 +803,9 @@ public: constexpr index_type index_bounds() const noexcept { - index_type extents; + size_type extents[rank]; m_ranges.serialize(extents); - return extents; + return{ extents }; } template @@ -874,32 +822,28 @@ public: constexpr const_iterator begin() const noexcept { - return const_iterator(*this); + return const_iterator(*this, index_type::zero()); } constexpr const_iterator end() const noexcept { - index_type boundary; - m_ranges.serialize(boundary); return const_iterator(*this, this->index_bounds()); } }; template -class strided_bounds : private details::coordinate_facade, SizeType, Rank> +class strided_bounds { - using Base = details::coordinate_facade, SizeType, Rank>; - friend Base; template friend class strided_bounds; public: - using Base::rank; - using reference = typename Base::reference; - using const_reference = typename Base::const_reference; - using size_type = typename Base::value_type; - using difference_type = typename Base::value_type; - using value_type = typename Base::value_type; + static const size_t rank = Rank; + using reference = typename SizeType&; + using const_reference = typename const SizeType&; + using size_type = typename SizeType; + using difference_type = typename SizeType; + using value_type = typename SizeType; using index_type = index; using iterator = bounds_iterator; using const_iterator = bounds_iterator; @@ -907,57 +851,52 @@ public: static const size_t static_size = dynamic_range; using sliced_type = std::conditional_t, void>; using mapping_type = generalized_mapping_tag; - constexpr strided_bounds(const strided_bounds &) = default; + constexpr strided_bounds(const strided_bounds &) noexcept = default; template - constexpr strided_bounds(const strided_bounds &other) - : Base(other), m_strides(other.strides) - { - } - - constexpr strided_bounds(const index_type &extents, const index_type &strides) - : m_strides(strides) - { - for (size_t i = 0; i < rank; i++) - Base::elems[i] = extents[i]; - } - constexpr strided_bounds(const value_type(&values)[rank], index_type strides) - : Base(values), m_strides(std::move(strides)) - { - } + constexpr strided_bounds(const strided_bounds &other) noexcept + : m_extents(other.extents), m_strides(other.strides) + {} + constexpr strided_bounds(const index_type &extents, const index_type &strides) noexcept + : m_extents(extents), m_strides(strides) + {} constexpr index_type strides() const noexcept - { - return m_strides; + { + return m_strides; } constexpr size_type total_size() const noexcept { size_type ret = 0; for (size_t i = 0; i < rank; ++i) - ret += (Base::elems[i] - 1) * m_strides[i]; + { + ret += (m_extents[i] - 1) * m_strides[i]; + } return ret + 1; } constexpr size_type size() const noexcept { size_type ret = 1; for (size_t i = 0; i < rank; ++i) - ret *= Base::elems[i]; + { + ret *= m_extents[i]; + } return ret; } constexpr bool contains(const index_type& idx) const noexcept { for (size_t i = 0; i < rank; ++i) { - if (idx[i] < 0 || idx[i] >= Base::elems[i]) + if (idx[i] < 0 || idx[i] >= m_extents[i]) return false; } return true; } - constexpr size_type linearize(const index_type & idx) const + constexpr size_type linearize(const index_type & idx) const noexcept { size_type ret = 0; for (size_t i = 0; i < rank; i++) { - fail_fast_assert(idx[i] < Base::elems[i], "index is out of bounds of the array"); + fail_fast_assert(idx[i] < m_extents[i], "index is out of bounds of the array"); ret += idx[i] * m_strides[i]; } return ret; @@ -969,27 +908,28 @@ public: template 1), typename Ret = std::enable_if_t> constexpr sliced_type slice() const { - return{ (value_type(&)[rank - 1])Base::elems[1], sliced_type::index_type::shift_left(m_strides) }; + return{ sliced_type::index_type::shift_left(m_extents), sliced_type::index_type::shift_left(m_strides) }; } template constexpr size_type extent() const noexcept { static_assert(Dim < Rank, "dimension should be less than rank (dimension count starts from 0)"); - return Base::elems[Dim]; + return m_extents[Dim]; } constexpr index_type index_bounds() const noexcept { - return index_type(Base::elems); + return m_extents; } const_iterator begin() const noexcept { - return const_iterator{ *this }; + return const_iterator{ *this, index_type::zero() }; } const_iterator end() const noexcept { return const_iterator{ *this, index_bounds() }; } private: + index_type m_extents; index_type m_strides; }; @@ -1017,9 +957,9 @@ public: using typename Base::difference_type; using typename Base::value_type; using index_type = value_type; - using index_size_type = typename IndexType::size_type; + using index_size_type = typename IndexType::value_type; template - explicit bounds_iterator(const Bounds & bnd, value_type curr = value_type{}) noexcept + explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept : boundary(bnd.index_bounds()) , curr( std::move(curr) ) { @@ -1210,7 +1150,7 @@ public: using typename Base::difference_type; using typename Base::value_type; using index_type = value_type; - using index_size_type = typename index_type::size_type; + using index_size_type = typename index_type::value_type; template explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) noexcept @@ -1327,11 +1267,14 @@ namespace details constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) noexcept { auto extents = bnd.index_bounds(); - typename Bounds::index_type stride; - stride[Bounds::rank - 1] = 1; - for (size_t i = Bounds::rank - 1; Bounds::rank > 1 && i > 0; --i) - stride[i-1] = stride[i] * extents[i]; - return stride; + Bounds::size_type stride[Bounds::rank]; + + stride[Bounds::rank - 1] = 1; + for (size_t i = Bounds::rank - 1; Bounds::rank > 1 && i > 0; --i) + { + stride[i - 1] = stride[i] * extents[i]; + } + return{ stride }; } template diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index 918df9e..ec10bbd 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -552,26 +552,6 @@ SUITE(array_view_tests) CHECK_THROW(av.section(5, 5), fail_fast); } - { - // zero stride - strided_array_view sav{ av, {{4}, {}} }; - CHECK(sav[0] == 0); - CHECK(sav[3] == 0); - CHECK_THROW(sav[4], fail_fast); - } - - { - // zero extent - strided_array_view sav{ av,{ {},{1} } }; - CHECK_THROW(sav[0], fail_fast); - } - - { - // zero extent and stride - strided_array_view sav{ av,{ {},{} } }; - CHECK_THROW(sav[0], fail_fast); - } - { // strided array ctor with matching strided bounds strided_array_view sav{ arr,{ 4, 1 } }; @@ -627,6 +607,9 @@ SUITE(array_view_tests) #ifdef CONFIRM_COMPILATION_ERRORS { + strided_array_view sav{ av,{ { 4 },{} } }; + strided_array_view sav{ av,{ {},{ 1 } } }; + strided_array_view sav{ av,{ {},{} } }; strided_array_view sav0{ av.data(), { 3, 2 } }; strided_array_view sav1{ arr, { 1 } }; strided_array_view sav2{ arr, { 1,1,1 } }; From 546f8cc1306ec69cc3a8f292785658da8caf157a Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Mon, 5 Oct 2015 21:04:56 -0700 Subject: [PATCH 44/59] Added tests for index size_type conversions --- include/array_view.h | 106 +++++++++---------- tests/array_view_tests.cpp | 209 +++++++++++++++++++++++++++++++++---- 2 files changed, 243 insertions(+), 72 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index aa1b4e5..98bbadf 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -70,7 +70,7 @@ namespace details template struct SizeTypeTraits { - static const size_t max_value = std::is_signed::value ? static_cast::type>(-1) / 2 : static_cast(-1); + static const SizeType max_value = std::is_signed::value ? static_cast::type>(-1) / 2 : static_cast(-1); }; template @@ -108,6 +108,9 @@ public: using reference = std::add_lvalue_reference_t; using const_reference = std::add_lvalue_reference_t>; + constexpr index() noexcept + {} + constexpr index(const value_type(&values)[Rank]) noexcept { std::copy(values, values + Rank, elems); @@ -120,36 +123,29 @@ public: std::copy(begin(il), end(il), elems); } - constexpr index(const index& other) noexcept = default; + constexpr index(const index& other) noexcept = default; // copy from index over smaller domain - template - constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value <= details::SizeTypeTraits::max_value), const index>::type& other) noexcept + template ::max_value <= details::SizeTypeTraits::max_value), + typename Other = std::enable_if_t>> + constexpr index(const index& other) noexcept { std::copy(other.elems, other.elems + Rank, elems); } // copy from index over larger domain - template - constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value > details::SizeTypeTraits::max_value), const index>::type& other) noexcept + template ::max_value > details::SizeTypeTraits::max_value), + typename Other = std::enable_if_t>> + constexpr index(const index& other, void* ptr = 0) noexcept { - for (size_t i = 0; i < Rank; ++i) - { - fail_fast_assert(other.elems[i] <= static_cast(SizeTypeTraits::max_value)); - elems[i] = static_cast(other.elems[i]); - } - } + bool ok = std::accumulate(other.elems, other.elems + Rank, true, + [&](bool b, OtherValueType val) { return b && (val <= static_cast(details::SizeTypeTraits::max_value)); } + ); - constexpr static index shift_left(const index& other) noexcept - { - value_type(&arr)[Rank] = (value_type(&)[Rank])(*(other.elems + 1)); - return index(arr); - } - - constexpr static index zero() noexcept - { - value_type zero[Rank] = {}; - return index(zero); + fail_fast_assert(ok, "other value must fit in the new domain"); + std::transform(other.elems, other.elems + rank, elems, [&](OtherValueType val) { return static_cast(val); }); } constexpr index& operator=(const index& rhs) noexcept = default; @@ -230,7 +226,7 @@ public: return ret; } - friend static constexpr index operator*(value_type v, const index& rhs) noexcept + friend constexpr index operator*(value_type v, const index& rhs) noexcept { return rhs * v; } @@ -246,6 +242,7 @@ public: std::transform(elems, elems + rank, elems, [v](value_type x) { return std::divides{}(x, v); }); return *this; } + private: value_type elems[Rank] = {}; }; @@ -262,44 +259,34 @@ public: using reference = std::add_lvalue_reference_t; using const_reference = std::add_lvalue_reference_t>; - constexpr index(value_type e0) noexcept : value(e0) + constexpr index() noexcept : value(0) {} - constexpr index(const value_type(&values)[1]) noexcept : index(values[0]) + constexpr index(value_type e) noexcept : value(e) {} - // Preconditions: il.size() == rank - constexpr index(std::initializer_list il) noexcept - { - fail_fast_assert(il.size() == rank, "Size of the initializer list must match the rank of the array"); - value = begin(il)[0]; - } + constexpr index(const value_type(&values)[1]) noexcept : index(values[0]) + {} constexpr index(const index &) noexcept = default; - template - constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value <= details::SizeTypeTraits::max_value), const index<1, OtherValueType>>::type& other) noexcept + template ::max_value <= details::SizeTypeTraits::max_value), + typename Other = std::enable_if_t>> + constexpr index(const index<1, OtherValueType>& other) noexcept { value = static_cast(other.value); } - template - constexpr index(typename std::enable_if_t<(details::SizeTypeTraits::max_value > details::SizeTypeTraits::max_value), const index<1, OtherValueType>>::type& other) noexcept + template ::max_value > details::SizeTypeTraits::max_value), + typename Other = std::enable_if_t>> + constexpr index(const index<1, OtherValueType>& other, void* ptr=0) noexcept { - fail_fast_assert(other.value <= static_cast(SizeTypeTraits::max_value)); + fail_fast_assert(other.value <= static_cast(details::SizeTypeTraits::max_value)); value = static_cast(other.value); } - constexpr static index shift_left(const index<2, value_type>& other) noexcept - { - return other.elems[1]; - } - - constexpr static index zero() noexcept - { - return 0; - } - // Preconditions: component_idx < 1 constexpr reference operator[](value_type component_idx) noexcept { @@ -388,7 +375,7 @@ public: value /= v; return *this; } - friend static constexpr index operator*(value_type v, const index& rhs) noexcept + friend constexpr index operator*(value_type v, const index& rhs) noexcept { return{ rhs * v }; } @@ -822,7 +809,7 @@ public: constexpr const_iterator begin() const noexcept { - return const_iterator(*this, index_type::zero()); + return const_iterator(*this); } constexpr const_iterator end() const noexcept @@ -908,7 +895,7 @@ public: template 1), typename Ret = std::enable_if_t> constexpr sliced_type slice() const { - return{ sliced_type::index_type::shift_left(m_extents), sliced_type::index_type::shift_left(m_strides) }; + return{ details::shift_left(m_extents), details::shift_left(m_strides) }; } template constexpr size_type extent() const noexcept @@ -922,7 +909,7 @@ public: } const_iterator begin() const noexcept { - return const_iterator{ *this, index_type::zero() }; + return const_iterator{ *this }; } const_iterator end() const noexcept { @@ -959,9 +946,9 @@ public: using index_type = value_type; using index_size_type = typename IndexType::value_type; template - explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept + explicit bounds_iterator(const Bounds& bnd, value_type curr = value_type{}) noexcept : boundary(bnd.index_bounds()) - , curr( std::move(curr) ) + , curr(std::move(curr)) { static_assert(is_bounds::value, "Bounds type must be provided"); } @@ -1270,13 +1257,24 @@ namespace details Bounds::size_type stride[Bounds::rank]; stride[Bounds::rank - 1] = 1; - for (size_t i = Bounds::rank - 1; Bounds::rank > 1 && i > 0; --i) + for (size_t i = 1; i < Bounds::rank; ++i) { - stride[i - 1] = stride[i] * extents[i]; + stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i]; } return{ stride }; } + template 1), typename Ret = std::enable_if_t>> + constexpr Ret shift_left(const index& other) noexcept + { + Ret ret; + for (size_t i = 0; i < Rank - 1; ++i) + { + ret[i] = other[i + 1]; + } + return ret; + } + template void verifyBoundsReshape(const BoundsSrc &src, const BoundsDest &dest) { diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index ec10bbd..a56d0f2 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -552,6 +552,26 @@ SUITE(array_view_tests) CHECK_THROW(av.section(5, 5), fail_fast); } + { + // zero stride + strided_array_view sav{ av,{ { 4 },{} } }; + CHECK(sav[0] == 0); + CHECK(sav[3] == 0); + CHECK_THROW(sav[4], fail_fast); + } + + { + // zero extent + strided_array_view sav{ av,{ {},{ 1 } } }; + CHECK_THROW(sav[0], fail_fast); + } + + { + // zero extent and stride + strided_array_view sav{ av,{ {},{} } }; + CHECK_THROW(sav[0], fail_fast); + } + { // strided array ctor with matching strided bounds strided_array_view sav{ arr,{ 4, 1 } }; @@ -607,9 +627,6 @@ SUITE(array_view_tests) #ifdef CONFIRM_COMPILATION_ERRORS { - strided_array_view sav{ av,{ { 4 },{} } }; - strided_array_view sav{ av,{ {},{ 1 } } }; - strided_array_view sav{ av,{ {},{} } }; strided_array_view sav0{ av.data(), { 3, 2 } }; strided_array_view sav1{ arr, { 1 } }; strided_array_view sav2{ arr, { 1,1,1 } }; @@ -618,27 +635,26 @@ SUITE(array_view_tests) strided_array_view sav5{ av.as_array_view(dim<2>(), dim<2>()), { 1 } }; strided_array_view sav6{ av.as_array_view(dim<2>(), dim<2>()), { 1,1,1 } }; strided_array_view sav7{ av.as_array_view(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } }; + + index<1> index{ 0, 1 }; + strided_array_view sav8{ arr,{ 1,{ 1,1 } } }; +#ifdef _MSC_VER + strided_array_view sav9{ arr,{ { 1,1 },{ 1,1 } } }; +#endif + strided_array_view sav10{ av,{ 1,{ 1,1 } } }; +#ifdef _MSC_VER + strided_array_view sav11{ av,{ { 1,1 },{ 1,1 } } }; +#endif } #endif - + { - // stride initializer list size should match the rank of the array - CHECK_THROW((index<1>{ 0,1 }), fail_fast); - CHECK_THROW((strided_array_view{ arr, {1, {1,1}} }), fail_fast); -#ifdef _MSC_VER - CHECK_THROW((strided_array_view{ arr, {{1,1 }, {1,1}} }), fail_fast); -#endif - CHECK_THROW((strided_array_view{ av, {1, {1,1}} }), fail_fast); -#ifdef _MSC_VER - CHECK_THROW((strided_array_view{ av, {{1,1 }, {1,1}} }), fail_fast); -#endif CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast); CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast); #ifdef _MSC_VER CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast); #endif } - } TEST(strided_array_view_type_conversion) @@ -856,7 +872,18 @@ SUITE(array_view_tests) } { - index<2> k = index<2>::shift_left(i); + index<3> k = 3 * i; + + CHECK(i[0] == 0); + CHECK(i[1] == 1); + CHECK(i[2] == 2); + CHECK(k[0] == 0); + CHECK(k[1] == 3); + CHECK(k[2] == 6); + } + + { + index<2> k = details::shift_left(i); CHECK(i[0] == 0); CHECK(i[1] == 1); @@ -972,7 +999,7 @@ SUITE(array_view_tests) auto bounds = strided_bounds<1>({ length }, { 2 }); #else auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 }); -#endif +#endif strided_array_view strided(&av.data()[1], av.size() - 1, bounds); CHECK(strided.size() == length); @@ -1033,7 +1060,7 @@ SUITE(array_view_tests) for (unsigned int k = 0; k < section.extent<2>(); ++k) { auto idx = index<3>{ i,j,k }; // avoid braces in the CHECK macro - CHECK(section[idx] == expected[2 * i + 2 * j + k]); + CHECK(section[idx] == expected[2 * i + 2 * j + k]); } } @@ -1151,6 +1178,152 @@ SUITE(array_view_tests) } + template + index Convert(index index) + { + return{ index }; + } + + TEST(DomainConverters) + { + // to smaller + { + index<2, int> int_index{ 0,1 }; + index<2, short> short_index{ int_index }; + + CHECK(short_index[0] == 0); + CHECK(short_index[1] == 1); + } + + // to smaller (failure) + { + index<2, int> big_int_index{ INT_MAX, 1 }; + CHECK_THROW((Convert<2,int, short int>(big_int_index)), fail_fast); + } + + // to same, sign mismatch + { + index<2, int> int_index{ 0,1 }; + index<2, unsigned int> uint_index{ int_index }; + + CHECK(uint_index[0] == 0); + CHECK(uint_index[1] == 1); + } + + // to same, sign mismatch, reversed + { + index<2, unsigned int> uint_index{ 0,1 }; + index<2, int> int_index{ uint_index }; + + CHECK(int_index[0] == 0); + CHECK(int_index[1] == 1); + } + + // to smaller, sign mismatch + { + index<2, int> int_index{ 0,1 }; + index<2, unsigned short> ushort_index{ int_index }; + + CHECK(ushort_index[0] == 0); + CHECK(ushort_index[1] == 1); + } + + // to bigger + { + index<2, int> int_index{ 0,1 }; + index<2, long long> longlong_index{ int_index }; + + CHECK(longlong_index[0] == 0); + CHECK(longlong_index[1] == 1); + } + + // to bigger with max index + { + index<2, int> big_int_index{ INT_MAX, 1 }; + index<2, long long> longlong_index{ big_int_index }; + + CHECK(longlong_index[0] == INT_MAX); + CHECK(longlong_index[1] == 1); + } + + // to bigger, sign mismatch + { + index<2, int> int_index{ 0,1 }; + index<2, unsigned long long> ulonglong_index{ int_index }; + + CHECK(ulonglong_index[0] == 0); + CHECK(ulonglong_index[1] == 1); + } + + } + + TEST(DomainConvertersRank1) + { + // to smaller + { + index<1, int> int_index{ 0 }; + index<1, short> short_index{ int_index }; + + CHECK(short_index[0] == 0); + } + + // to smaller (failure) + { + index<1, int> big_int_index{ INT_MAX }; + + CHECK_THROW((Convert<1, int, short int>(big_int_index)), fail_fast); + } + + // to same, sign mismatch + { + index<1, int> int_index{ 0 }; + index<1, unsigned int> uint_index{ int_index }; + + CHECK(uint_index[0] == 0); + } + + // to same, sign mismatch, reversed + { + index<1, unsigned int> uint_index{ 0 }; + index<1, int> int_index{ uint_index }; + + CHECK(int_index[0] == 0); + } + + // to smaller, sign mismatch + { + index<1, int> int_index{ 0 }; + index<1, unsigned short> ushort_index{ int_index }; + + CHECK(ushort_index[0] == 0); + } + + // to bigger + { + index<1, int> int_index{ 0 }; + index<1, long long> longlong_index{ int_index }; + + CHECK(longlong_index[0] == 0); + } + + // to bigger with max index + { + index<1, int> big_int_index{ INT_MAX }; + index<1, long long> longlong_index{ big_int_index }; + + CHECK(longlong_index[0] == INT_MAX); + } + + // to bigger, sign mismatch + { + index<1, int> int_index{ 0 }; + index<1, unsigned long long> ulonglong_index{ int_index }; + + CHECK(ulonglong_index[0] == 0); + } + + } + TEST(constructors) { array_view av(nullptr); From fdf864347150a108a33a467bc7ba3efd1ad78b2f Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 14 Oct 2015 10:46:22 -0700 Subject: [PATCH 45/59] Fixes for gcc --- include/array_view.h | 36 ++++++++++++++++++------------------ tests/array_view_tests.cpp | 13 +++++++------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 98bbadf..3502076 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -686,6 +686,17 @@ namespace details { return TypeListIndexer(obj); } + + template 1), typename Ret = std::enable_if_t>> + constexpr Ret shift_left(const index& other) noexcept + { + Ret ret; + for (size_t i = 0; i < Rank - 1; ++i) + { + ret[i] = other[i + 1]; + } + return ret; + } } template @@ -790,7 +801,7 @@ public: constexpr index_type index_bounds() const noexcept { - size_type extents[rank]; + size_type extents[rank] = {}; m_ranges.serialize(extents); return{ extents }; } @@ -826,11 +837,11 @@ class strided_bounds public: static const size_t rank = Rank; - using reference = typename SizeType&; - using const_reference = typename const SizeType&; - using size_type = typename SizeType; - using difference_type = typename SizeType; - using value_type = typename SizeType; + using reference = SizeType&; + using const_reference = const SizeType&; + using size_type = SizeType; + using difference_type = SizeType; + using value_type = SizeType; using index_type = index; using iterator = bounds_iterator; using const_iterator = bounds_iterator; @@ -1254,7 +1265,7 @@ namespace details constexpr std::enable_if_t::value, typename Bounds::index_type> make_stride(const Bounds& bnd) noexcept { auto extents = bnd.index_bounds(); - Bounds::size_type stride[Bounds::rank]; + typename Bounds::size_type stride[Bounds::rank] = {}; stride[Bounds::rank - 1] = 1; for (size_t i = 1; i < Bounds::rank; ++i) @@ -1264,17 +1275,6 @@ namespace details return{ stride }; } - template 1), typename Ret = std::enable_if_t>> - constexpr Ret shift_left(const index& other) noexcept - { - Ret ret; - for (size_t i = 0; i < Rank - 1; ++i) - { - ret[i] = other[i + 1]; - } - return ret; - } - template void verifyBoundsReshape(const BoundsSrc &src, const BoundsDest &dest) { diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index a56d0f2..f84e908 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1197,7 +1198,7 @@ SUITE(array_view_tests) // to smaller (failure) { - index<2, int> big_int_index{ INT_MAX, 1 }; + index<2, int> big_int_index{ std::numeric_limits::max(), 1 }; CHECK_THROW((Convert<2,int, short int>(big_int_index)), fail_fast); } @@ -1239,10 +1240,10 @@ SUITE(array_view_tests) // to bigger with max index { - index<2, int> big_int_index{ INT_MAX, 1 }; + index<2, int> big_int_index{ std::numeric_limits::max(), 1 }; index<2, long long> longlong_index{ big_int_index }; - CHECK(longlong_index[0] == INT_MAX); + CHECK(longlong_index[0] == std::numeric_limits::max()); CHECK(longlong_index[1] == 1); } @@ -1269,7 +1270,7 @@ SUITE(array_view_tests) // to smaller (failure) { - index<1, int> big_int_index{ INT_MAX }; + index<1, int> big_int_index{ std::numeric_limits::max() }; CHECK_THROW((Convert<1, int, short int>(big_int_index)), fail_fast); } @@ -1308,10 +1309,10 @@ SUITE(array_view_tests) // to bigger with max index { - index<1, int> big_int_index{ INT_MAX }; + index<1, int> big_int_index{ std::numeric_limits::max() }; index<1, long long> longlong_index{ big_int_index }; - CHECK(longlong_index[0] == INT_MAX); + CHECK(longlong_index[0] == std::numeric_limits::max()); } // to bigger, sign mismatch From f972b2d68c9a9d7ce151d93b3a3b3b2da9ecb6eb Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 15 Oct 2015 13:00:10 -0700 Subject: [PATCH 46/59] Adding g++-5 libraries to clang travis configuration to fix build break --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 524f1fb..3c64230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ matrix: packages: - clang-3.6 - cmake + - g++-5 sources: &sources - ubuntu-toolchain-r-test - llvm-toolchain-precise-3.6 From 2cdedda7e4d85f356b8ef66f2d6f7e778538ba00 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 15 Oct 2015 13:19:24 -0700 Subject: [PATCH 47/59] Adding missing include library to array_view.h --- include/array_view.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/array_view.h b/include/array_view.h index 3502076..c884c11 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include From 01868f2516ee04e2129ceafe341fd5fe0d112e01 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Thu, 15 Oct 2015 16:48:38 -0700 Subject: [PATCH 48/59] Fix missing header for std::divides. --- include/array_view.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/array_view.h b/include/array_view.h index c884c11..cc7ab23 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "fail_fast.h" #ifdef _MSC_VER From c973e82dff09144005e883a3daceded35044472f Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Thu, 15 Oct 2015 17:05:19 -0700 Subject: [PATCH 49/59] Added AppVeyor CI status badge. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d96dec..c687673 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GSL: Guidelines Support Library [![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL) +# GSL: Guidelines Support Library [![Build Status](https://travis-ci.org/Microsoft/GSL.svg?branch=master)](https://travis-ci.org/Microsoft/GSL) [![Build status](https://ci.appveyor.com/api/projects/status/github/Microsoft/GSL?svg=true)](https://ci.appveyor.com/project/neilmacintosh/GSL) The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). From a4654a46b535100f53143b6c616425cf293b6a3b Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 16 Oct 2015 12:15:22 -0700 Subject: [PATCH 50/59] Removed arrow_proxy class, fixes bugs in reverse bounds_iterator --- include/array_view.h | 269 +++++++++++++++++++------------------ tests/array_view_tests.cpp | 63 ++++++++- 2 files changed, 199 insertions(+), 133 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index cc7ab23..a31efd8 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -74,25 +74,6 @@ namespace details { static const SizeType max_value = std::is_signed::value ? static_cast::type>(-1) / 2 : static_cast(-1); }; - - template - class arrow_proxy - { - public: - explicit arrow_proxy(T t) - : val(t) - {} - const T operator*() const noexcept - { - return val; - } - const T* operator->() const noexcept - { - return &val; - } - private: - T val; - }; } template @@ -730,8 +711,9 @@ public: using size_type = SizeType; using index_type = index; - using iterator = bounds_iterator; - using const_iterator = bounds_iterator; + using const_index_type = std::add_const_t; + using iterator = bounds_iterator; + using const_iterator = bounds_iterator; using difference_type = ptrdiff_t; using sliced_type = static_bounds; using mapping_type = contiguous_mapping_tag; @@ -822,7 +804,7 @@ public: constexpr const_iterator begin() const noexcept { - return const_iterator(*this); + return const_iterator(*this, index_type{}); } constexpr const_iterator end() const noexcept @@ -845,8 +827,9 @@ public: using difference_type = SizeType; using value_type = SizeType; using index_type = index; - using iterator = bounds_iterator; - using const_iterator = bounds_iterator; + using const_index_type = std::add_const_t; + using iterator = bounds_iterator; + using const_iterator = bounds_iterator; static const int dynamic_rank = rank; static const size_t static_size = dynamic_range; using sliced_type = std::conditional_t, void>; @@ -920,11 +903,11 @@ public: { return m_extents; } - const_iterator begin() const noexcept + constexpr const_iterator begin() const noexcept { - return const_iterator{ *this }; + return const_iterator{ *this, index_type{} }; } - const_iterator end() const noexcept + constexpr const_iterator end() const noexcept { return const_iterator{ *this, index_bounds() }; } @@ -941,15 +924,11 @@ template struct is_bounds> : std::integral_constant {}; template -class bounds_iterator - : public std::iterator, - const IndexType> +class bounds_iterator: public std::iterator { private: - using Base = std::iterator , const IndexType>; + using Base = std::iterator ; + public: static const size_t rank = IndexType::rank; using typename Base::reference; @@ -959,79 +938,88 @@ public: using index_type = value_type; using index_size_type = typename IndexType::value_type; template - explicit bounds_iterator(const Bounds& bnd, value_type curr = value_type{}) noexcept - : boundary(bnd.index_bounds()) - , curr(std::move(curr)) + explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept + : boundary(bnd.index_bounds()), curr(std::move(curr)) { static_assert(is_bounds::value, "Bounds type must be provided"); } - reference operator*() const noexcept + + constexpr reference operator*() const noexcept { return curr; } - pointer operator->() const noexcept + + constexpr pointer operator->() const noexcept { - return details::arrow_proxy{ curr }; + return &curr; } - bounds_iterator& operator++() noexcept + + constexpr bounds_iterator& operator++() noexcept { for (size_t i = rank; i-- > 0;) { - if (++curr[i] < boundary[i]) + if (curr[i] < boundary[i] - 1) { + curr[i]++; return *this; } - else - { - curr[i] = 0; - } + curr[i] = 0; } // If we're here we've wrapped over - set to past-the-end. - for (size_t i = 0; i < rank; ++i) - { - curr[i] = boundary[i]; - } + curr = boundary; return *this; } - bounds_iterator operator++(int) noexcept + + constexpr bounds_iterator operator++(int) noexcept { auto ret = *this; ++(*this); return ret; } - bounds_iterator& operator--() noexcept + + constexpr bounds_iterator& operator--() noexcept { - for (size_t i = rank; i-- > 0;) + if (!less(curr, boundary)) { - if (curr[i]-- > 0) - { - return *this; - } - else + // if at the past-the-end, set to last element + for (size_t i = 0; i < rank; ++i) { curr[i] = boundary[i] - 1; } + return *this; + } + for (size_t i = rank; i-- > 0;) + { + if (curr[i] >= 1) + { + curr[i]--; + return *this; + } + curr[i] = boundary[i] - 1; } // If we're here the preconditions were violated // "pre: there exists s such that r == ++s" fail_fast_assert(false); return *this; } - bounds_iterator operator--(int) noexcept + + constexpr bounds_iterator operator--(int) noexcept { auto ret = *this; --(*this); return ret; } - bounds_iterator operator+(difference_type n) const noexcept + + constexpr bounds_iterator operator+(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret += n; } - bounds_iterator& operator+=(difference_type n) noexcept + + constexpr bounds_iterator& operator+=(difference_type n) noexcept { auto linear_idx = linearize(curr) + n; - value_type stride; + std::remove_const_t stride; stride[rank - 1] = 1; for (size_t i = rank - 1; i-- > 0;) { @@ -1042,76 +1030,84 @@ public: curr[i] = linear_idx / stride[i]; linear_idx = linear_idx % stride[i]; } + fail_fast_assert(!less(curr, index_type{}) && !less(boundary, curr), "index is out of bounds of the array"); return *this; } - bounds_iterator operator-(difference_type n) const noexcept + + constexpr bounds_iterator operator-(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret -= n; } - bounds_iterator& operator-=(difference_type n) noexcept + + constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const bounds_iterator& rhs) const noexcept + + constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept { return linearize(curr) - linearize(rhs.curr); } - reference operator[](difference_type n) const noexcept + + constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } - bool operator==(const bounds_iterator& rhs) const noexcept + + constexpr bool operator==(const bounds_iterator& rhs) const noexcept { return curr == rhs.curr; } - bool operator!=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const bounds_iterator& rhs) const noexcept + + constexpr bool operator<(const bounds_iterator& rhs) const noexcept { - for (size_t i = 0; i < rank; ++i) - { - if (curr[i] < rhs.curr[i]) - return true; - } - return false; + return less(curr, rhs.curr); } - bool operator<=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const bounds_iterator& rhs) const noexcept + + constexpr bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } + void swap(bounds_iterator& rhs) noexcept { std::swap(boundary, rhs.boundary); std::swap(curr, rhs.curr); } private: - index_size_type linearize(const value_type& idx) const noexcept + constexpr bool less(index_type& one, index_type& other) const noexcept + { + for (size_t i = 0; i < rank; ++i) + { + if (one[i] < other[i]) + return true; + } + return false; + } + + constexpr index_size_type linearize(const value_type& idx) const noexcept { // TODO: Smarter impl. // Check if past-the-end - bool pte = true; - for (size_t i = 0; i < rank; ++i) - { - if (idx[i] != boundary[i]) - { - pte = false; - break; - } - } index_size_type multiplier = 1; index_size_type res = 0; - if (pte) + if (!less(idx, boundary)) { res = 1; for (size_t i = rank; i-- > 0;) @@ -1130,19 +1126,15 @@ private: } return res; } + value_type boundary; - value_type curr; + std::remove_const_t curr; }; template -class bounds_iterator> - : public std::iterator, - ptrdiff_t, - const details::arrow_proxy>, - const index<1, SizeType>> +class bounds_iterator> : public std::iterator> { - using Base = std::iterator, ptrdiff_t, const details::arrow_proxy>, const index<1, SizeType>>; + using Base = std::iterator>; public: using typename Base::reference; @@ -1153,96 +1145,116 @@ public: using index_size_type = typename index_type::value_type; template - explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) noexcept - : curr( std::move(curr) ) + constexpr explicit bounds_iterator(const Bounds&, value_type curr) noexcept + : curr(std::move(curr)) {} - reference operator*() const noexcept + + constexpr reference operator*() const noexcept { return curr; } - pointer operator->() const noexcept + + constexpr pointer operator->() const noexcept { - return details::arrow_proxy{ curr }; + &curr; } - bounds_iterator& operator++() noexcept + + constexpr bounds_iterator& operator++() noexcept { ++curr; return *this; } - bounds_iterator operator++(int) noexcept + + constexpr bounds_iterator operator++(int) noexcept { auto ret = *this; ++(*this); return ret; } - bounds_iterator& operator--() noexcept + + constexpr bounds_iterator& operator--() noexcept { curr--; return *this; } - bounds_iterator operator--(int) noexcept + + constexpr bounds_iterator operator--(int) noexcept { auto ret = *this; --(*this); return ret; } - bounds_iterator operator+(difference_type n) const noexcept + + constexpr bounds_iterator operator+(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret += n; } - bounds_iterator& operator+=(difference_type n) noexcept + + constexpr bounds_iterator& operator+=(difference_type n) noexcept { curr += n; return *this; } - bounds_iterator operator-(difference_type n) const noexcept + + constexpr bounds_iterator operator-(difference_type n) const noexcept { bounds_iterator ret{ *this }; return ret -= n; } - bounds_iterator& operator-=(difference_type n) noexcept + + constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; } - difference_type operator-(const bounds_iterator& rhs) const noexcept + + constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept { return curr[0] - rhs.curr[0]; } - reference operator[](difference_type n) const noexcept + + constexpr reference operator[](difference_type n) const noexcept { return curr + n; } - bool operator==(const bounds_iterator& rhs) const noexcept + + constexpr bool operator==(const bounds_iterator& rhs) const noexcept { return curr == rhs.curr; } - bool operator!=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator!=(const bounds_iterator& rhs) const noexcept { return !(*this == rhs); } - bool operator<(const bounds_iterator& rhs) const noexcept + + constexpr bool operator<(const bounds_iterator& rhs) const noexcept { return curr[0] < rhs.curr[0]; } - bool operator<=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator<=(const bounds_iterator& rhs) const noexcept { return !(rhs < *this); } - bool operator>(const bounds_iterator& rhs) const noexcept + + constexpr bool operator>(const bounds_iterator& rhs) const noexcept { return rhs < *this; } - bool operator>=(const bounds_iterator& rhs) const noexcept + + constexpr bool operator>=(const bounds_iterator& rhs) const noexcept { return !(rhs > *this); } - void swap(bounds_iterator& rhs) noexcept + + constexpr void swap(bounds_iterator& rhs) noexcept { std::swap(curr, rhs.curr); } + private: - value_type curr; + std::remove_const_t curr; }; template @@ -1304,10 +1316,11 @@ public: using size_type = typename bounds_type::size_type; using index_type = typename bounds_type::index_type; using value_type = ValueType; + using const_value_type = std::add_const_t; using pointer = ValueType*; using reference = ValueType&; using iterator = std::conditional_t::value, contiguous_array_view_iterator, general_array_view_iterator>; - using const_iterator = std::conditional_t::value, contiguous_array_view_iterator>, general_array_view_iterator>>; + using const_iterator = std::conditional_t::value, contiguous_array_view_iterator>, general_array_view_iterator>>; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using sliced_type = std::conditional_t>; @@ -1360,7 +1373,7 @@ public: } constexpr iterator end() const { - return iterator {this}; + return iterator {this, false}; } constexpr const_iterator cbegin() const { @@ -1368,7 +1381,7 @@ public: } constexpr const_iterator cend() const { - return const_iterator {reinterpret_cast *>(this)}; + return const_iterator {reinterpret_cast *>(this), false}; } constexpr reverse_iterator rbegin() const @@ -1999,8 +2012,8 @@ private: { fail_fast_assert(m_pdata >= m_validator->m_pdata && m_pdata < m_validator->m_pdata + m_validator->size(), "iterator is out of range of the array"); } - contiguous_array_view_iterator (const ArrayView *container, bool isbegin = false) : - m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) { } + contiguous_array_view_iterator (const ArrayView *container, bool isbegin) : + m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {} public: reference operator*() const noexcept { @@ -2115,16 +2128,16 @@ private: friend class basic_array_view; const ArrayView * m_container; typename ArrayView::bounds_type::iterator m_itr; - general_array_view_iterator(const ArrayView *container, bool isbegin = false) : + general_array_view_iterator(const ArrayView *container, bool isbegin) : m_container(container), m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end()) { } public: - reference operator*() const noexcept + reference operator*() noexcept { return (*m_container)[*m_itr]; } - pointer operator->() const noexcept + pointer operator->() noexcept { return &(*m_container)[*m_itr]; } diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index f84e908..cf83fd5 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -925,11 +925,35 @@ SUITE(array_view_tests) } } - size_t idx = 0; - for (auto num : section) + size_t check_sum = 0; + for (size_t i = 0; i < length; ++i) { - CHECK(num == av[idx][1]); - idx++; + check_sum += av[i][1]; + } + + { + size_t idx = 0; + size_t sum = 0; + for (auto num : section) + { + CHECK(num == av[idx][1]); + sum += num; + idx++; + } + + CHECK(sum == check_sum); + } + { + size_t idx = length - 1; + size_t sum = 0; + for (auto iter = section.rbegin(); iter != section.rend(); ++iter) + { + CHECK(*iter == av[idx][1]); + sum += *iter; + idx--; + } + + CHECK(sum == check_sum); } } @@ -1688,7 +1712,7 @@ SUITE(array_view_tests) CHECK_THROW(f(), fail_fast); } - TEST(AsWriteableBytes) + TEST(AsWriteableBytes) { int a[] = { 1, 2, 3, 4 }; @@ -1714,7 +1738,36 @@ SUITE(array_view_tests) CHECK(wav.data() == (byte*)&a[0]); CHECK(wav.length() == sizeof(a)); } + } + TEST(NonConstIterator) + { + int a[] = { 1, 2, 3, 4 }; + + { + array_view av = a; + auto wav = av.as_writeable_bytes(); + for (auto& b : wav) + { + b = byte(0); + } + for (size_t i = 0; i < 4; ++i) + { + CHECK(a[i] == 0); + } + } + + { + array_view av = a; + for (auto& n : av) + { + n = 1; + } + for (size_t i = 0; i < 4; ++i) + { + CHECK(a[i] == 1); + } + } } TEST(ArrayViewComparison) From a544ada8fe998bc7c47be942008430a7ec8366da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Garc=C3=ADa=20Salas?= Date: Sat, 17 Oct 2015 08:53:58 +0200 Subject: [PATCH 51/59] std::hash support for gsl::not_null. --- include/gsl.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/gsl.h b/include/gsl.h index 519682b..ca37848 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -197,6 +197,19 @@ private: } // namespace gsl +namespace std +{ + template + struct hash> + { + size_t operator()(const gsl::not_null & value) const + { + return hash{}(value); + } + }; + +} // namespace std + #ifdef _MSC_VER #undef constexpr From 8e2acc9c901c658cfcce013ecaf594b9565b2fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Garc=C3=ADa=20Salas?= Date: Sat, 17 Oct 2015 09:28:05 +0200 Subject: [PATCH 52/59] std::hash support for gsl::not_null. --- include/gsl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index ca37848..ec75723 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -200,11 +200,11 @@ private: namespace std { template - struct hash> + struct hash> { - size_t operator()(const gsl::not_null & value) const + size_t operator()(const gsl::not_null & value) const { - return hash{}(value); + return hash{}(value); } }; From 5f26ddac70f05766070b5b62ecabb7086f0df7c2 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 16 Oct 2015 17:30:48 -0700 Subject: [PATCH 53/59] Replaced index constructor from initializer list by a constructor from static list Conflicts: include/array_view.h --- include/array_view.h | 11 ++-- tests/array_view_tests.cpp | 110 +++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 25 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index a31efd8..a2ea49f 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -72,7 +72,7 @@ namespace details template struct SizeTypeTraits { - static const SizeType max_value = std::is_signed::value ? static_cast::type>(-1) / 2 : static_cast(-1); + static const SizeType max_value = std::numeric_limits::max(); }; } @@ -99,12 +99,9 @@ public: std::copy(values, values + Rank, elems); } - // Preconditions: il.size() == rank - constexpr index(std::initializer_list il) noexcept - { - fail_fast_assert(il.size() == Rank, "The size of the initializer list must match the rank of the array"); - std::copy(begin(il), end(il), elems); - } + template> + constexpr index(Ts... ds) noexcept : elems{ static_cast(ds)... } + {} constexpr index(const index& other) noexcept = default; diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp index cf83fd5..3a8acc2 100644 --- a/tests/array_view_tests.cpp +++ b/tests/array_view_tests.cpp @@ -16,16 +16,11 @@ #include #include -#include -#include -#include + #include #include #include #include -#include -#include - using namespace std; using namespace gsl; @@ -639,23 +634,14 @@ SUITE(array_view_tests) index<1> index{ 0, 1 }; strided_array_view sav8{ arr,{ 1,{ 1,1 } } }; -#ifdef _MSC_VER strided_array_view sav9{ arr,{ { 1,1 },{ 1,1 } } }; -#endif strided_array_view sav10{ av,{ 1,{ 1,1 } } }; -#ifdef _MSC_VER strided_array_view sav11{ av,{ { 1,1 },{ 1,1 } } }; -#endif + strided_array_view sav12{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1 } } }; + strided_array_view sav13{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } }; + strided_array_view sav14{ av.as_array_view(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } }; } #endif - - { - CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast); - CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast); -#ifdef _MSC_VER - CHECK_THROW((strided_array_view{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast); -#endif - } } TEST(strided_array_view_type_conversion) @@ -839,6 +825,94 @@ SUITE(array_view_tests) delete[] arr; } + TEST(index_constructors) + { + { + // components of the same type + index<3> i1(0, 1, 2); + CHECK(i1[0] == 0); + + // components of different types + size_t c0 = 0; + size_t c1 = 1; + index<3> i2(c0, c1, 2); + CHECK(i2[0] == 0); + + // from array + index<3> i3 = { 0,1,2 }; + CHECK(i3[0] == 0); + + // from other index of the same size type + index<3> i4 = i3; + CHECK(i4[0] == 0); + + // from other index of bigger size type + index<3, short> i5 = i4; + CHECK(i5[0] == 0); + + // from other index of smaller size type + index<3, long long> i6 = i4; + CHECK(i6[0] == 0); + + // default + index<3, long long> i7; + CHECK(i7[0] == 0); + + // default + index<3, long long> i9 = {}; + CHECK(i9[0] == 0); + } + + { + // components of the same type + index<1> i1(0); + CHECK(i1[0] == 0); + + // components of different types + size_t c0 = 0; + index<1> i2(c0); + CHECK(i2[0] == 0); + + // from array + index<1> i3 = { 0 }; + CHECK(i3[0] == 0); + + // from int + index<1> i4 = 0; + CHECK(i4[0] == 0); + + // from other index of the same size type + index<1> i5 = i3; + CHECK(i5[0] == 0); + + // from other index of bigger size type + index<1, short> i6 = i5; + CHECK(i6[0] == 0); + + // from other index of smaller size type + index<1, long long> i7 = i6; + CHECK(i7[0] == 0); + + // default + index<1, long long> i8; + CHECK(i8[0] == 0); + + // default + index<1, long long> i9 = {}; + CHECK(i9[0] == 0); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + index<3> i1(0, 1); + index<3> i2(0, 1, 2, 3); + index<3> i3 = { 0 }; + index<3> i4 = { 0, 1, 2, 3 }; + index<1> i5 = { 0,1 }; + } +#endif + } + TEST(index_operations) { size_t a[3] = { 0, 1, 2 }; From 1c208b33d0823dabed0832b91ce6e56fbcd046cd Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 16 Oct 2015 17:40:57 -0700 Subject: [PATCH 54/59] Removed specializations for Rank=1 --- include/array_view.h | 271 ++----------------------------------------- 1 file changed, 8 insertions(+), 263 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index a2ea49f..0145799 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -74,6 +74,13 @@ namespace details { static const SizeType max_value = std::numeric_limits::max(); }; + + + template + class are_integral : public std::integral_constant {}; + + template + class are_integral : public std::integral_constant::value && are_integral::value> {}; } template @@ -99,7 +106,7 @@ public: std::copy(values, values + Rank, elems); } - template> + template::value, typename Dummy = std::enable_if_t> constexpr index(Ts... ds) noexcept : elems{ static_cast(ds)... } {} @@ -227,142 +234,6 @@ private: value_type elems[Rank] = {}; }; -template -class index<1, ValueType> -{ - template - friend class index; - -public: - static const size_t rank = 1; - using value_type = std::remove_reference_t; - using reference = std::add_lvalue_reference_t; - using const_reference = std::add_lvalue_reference_t>; - - constexpr index() noexcept : value(0) - {} - - constexpr index(value_type e) noexcept : value(e) - {} - - constexpr index(const value_type(&values)[1]) noexcept : index(values[0]) - {} - - constexpr index(const index &) noexcept = default; - - template ::max_value <= details::SizeTypeTraits::max_value), - typename Other = std::enable_if_t>> - constexpr index(const index<1, OtherValueType>& other) noexcept - { - value = static_cast(other.value); - } - - template ::max_value > details::SizeTypeTraits::max_value), - typename Other = std::enable_if_t>> - constexpr index(const index<1, OtherValueType>& other, void* ptr=0) noexcept - { - fail_fast_assert(other.value <= static_cast(details::SizeTypeTraits::max_value)); - value = static_cast(other.value); - } - - // Preconditions: component_idx < 1 - constexpr reference operator[](value_type component_idx) noexcept - { - fail_fast_assert(component_idx == 0, "Component index must be less than rank"); - (void)(component_idx); - return value; - } - // Preconditions: component_idx < 1 - constexpr const_reference operator[](value_type component_idx) const noexcept - { - fail_fast_assert(component_idx == 0, "Component index must be less than rank"); - (void)(component_idx); - return value; - } - constexpr bool operator==(const index& rhs) const noexcept - { - return value == rhs.value; - } - constexpr bool operator!=(const index& rhs) const noexcept - { - return !(*this == rhs); - } - constexpr index operator+() const noexcept - { - return *this; - } - constexpr index operator-() const noexcept - { - return index(-value); - } - constexpr index operator+(const index& rhs) const noexcept - { - return index(value + rhs.value); - } - constexpr index operator-(const index& rhs) const noexcept - { - return index(value - rhs.value); - } - constexpr index& operator+=(const index& rhs) noexcept - { - value += rhs.value; - return *this; - } - constexpr index& operator-=(const index& rhs) noexcept - { - value -= rhs.value; - return *this; - } - constexpr index& operator++() noexcept - { - ++value; - return *this; - } - constexpr index operator++(int) noexcept - { - index ret = *this; - ++(*this); - return ret; - } - constexpr index& operator--() noexcept - { - --value; - return *this; - } - constexpr index operator--(int) noexcept - { - index ret = *this; - --(*this); - return ret; - } - constexpr index operator*(value_type v) const noexcept - { - return index(value * v); - } - constexpr index operator/(value_type v) const noexcept - { - return index(value / v); - } - constexpr index& operator*=(value_type v) noexcept - { - value *= v; - return *this; - } - constexpr index& operator/=(value_type v) noexcept - { - value /= v; - return *this; - } - friend constexpr index operator*(value_type v, const index& rhs) noexcept - { - return{ rhs * v }; - } -private: - value_type value; -}; - #ifndef _MSC_VER struct static_bounds_dynamic_range_t @@ -1128,132 +999,6 @@ private: std::remove_const_t curr; }; -template -class bounds_iterator> : public std::iterator> -{ - using Base = std::iterator>; - -public: - using typename Base::reference; - using typename Base::pointer; - using typename Base::difference_type; - using typename Base::value_type; - using index_type = value_type; - using index_size_type = typename index_type::value_type; - - template - constexpr explicit bounds_iterator(const Bounds&, value_type curr) noexcept - : curr(std::move(curr)) - {} - - constexpr reference operator*() const noexcept - { - return curr; - } - - constexpr pointer operator->() const noexcept - { - &curr; - } - - constexpr bounds_iterator& operator++() noexcept - { - ++curr; - return *this; - } - - constexpr bounds_iterator operator++(int) noexcept - { - auto ret = *this; - ++(*this); - return ret; - } - - constexpr bounds_iterator& operator--() noexcept - { - curr--; - return *this; - } - - constexpr bounds_iterator operator--(int) noexcept - { - auto ret = *this; - --(*this); - return ret; - } - - constexpr bounds_iterator operator+(difference_type n) const noexcept - { - bounds_iterator ret{ *this }; - return ret += n; - } - - constexpr bounds_iterator& operator+=(difference_type n) noexcept - { - curr += n; - return *this; - } - - constexpr bounds_iterator operator-(difference_type n) const noexcept - { - bounds_iterator ret{ *this }; - return ret -= n; - } - - constexpr bounds_iterator& operator-=(difference_type n) noexcept - { - return *this += -n; - } - - constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept - { - return curr[0] - rhs.curr[0]; - } - - constexpr reference operator[](difference_type n) const noexcept - { - return curr + n; - } - - constexpr bool operator==(const bounds_iterator& rhs) const noexcept - { - return curr == rhs.curr; - } - - constexpr bool operator!=(const bounds_iterator& rhs) const noexcept - { - return !(*this == rhs); - } - - constexpr bool operator<(const bounds_iterator& rhs) const noexcept - { - return curr[0] < rhs.curr[0]; - } - - constexpr bool operator<=(const bounds_iterator& rhs) const noexcept - { - return !(rhs < *this); - } - - constexpr bool operator>(const bounds_iterator& rhs) const noexcept - { - return rhs < *this; - } - - constexpr bool operator>=(const bounds_iterator& rhs) const noexcept - { - return !(rhs > *this); - } - - constexpr void swap(bounds_iterator& rhs) noexcept - { - std::swap(curr, rhs.curr); - } - -private: - std::remove_const_t curr; -}; - template bounds_iterator operator+(typename bounds_iterator::difference_type n, const bounds_iterator& rhs) noexcept { From 59cf62652a4bb6ee5809727f86ed7a5b218c3821 Mon Sep 17 00:00:00 2001 From: Matt Newport Date: Mon, 19 Oct 2015 18:55:46 -0700 Subject: [PATCH 55/59] Add .gitignore --- .gitignore | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5f5de3e..3fb78a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,13 @@ -tests/unittest-cpp \ No newline at end of file +tests/unittest-cpp +CMakeFiles +tests/CMakeFiles +tests/Debug +*.opensdf +*.sdf +tests/*tests.dir +*.vcxproj +*.vcxproj.filters +*.sln +*.tlog +Testing/Temporary/*.* +CMakeCache.txt From 9e9eddcddfef2fd6f80002f476cfb9f46b511c31 Mon Sep 17 00:00:00 2001 From: Matt Newport Date: Mon, 19 Oct 2015 18:58:26 -0700 Subject: [PATCH 56/59] Updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3fb78a5..ea47eb3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tests/*tests.dir *.tlog Testing/Temporary/*.* CMakeCache.txt +*.suo From 561da1cd0049b24bc2cb26a77e7ec4df43ed1f37 Mon Sep 17 00:00:00 2001 From: Kosov Eugene Date: Wed, 21 Oct 2015 13:31:00 +0300 Subject: [PATCH 57/59] fix clang warning on unused function parameter --- include/array_view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/array_view.h b/include/array_view.h index 0145799..14d8888 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -125,7 +125,7 @@ public: template ::max_value > details::SizeTypeTraits::max_value), typename Other = std::enable_if_t>> - constexpr index(const index& other, void* ptr = 0) noexcept + constexpr index(const index& other, void* = 0) noexcept { bool ok = std::accumulate(other.elems, other.elems + Rank, true, [&](bool b, OtherValueType val) { return b && (val <= static_cast(details::SizeTypeTraits::max_value)); } From 0cbdc7036d2499967c59c50587242f0611c969b6 Mon Sep 17 00:00:00 2001 From: Matt Newport Date: Mon, 26 Oct 2015 18:23:14 -0700 Subject: [PATCH 58/59] Fixed string_view::ensure_z() for const char*. --- include/string_view.h | 6 +++--- tests/string_view_tests.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/string_view.h b/include/string_view.h index 4076d52..7080ce5 100644 --- a/include/string_view.h +++ b/include/string_view.h @@ -82,9 +82,9 @@ template array_view ensure_sentinel(const T* seq, SizeType max = std::numeric_limits::max()) { auto cur = seq; - while ((cur - seq) < max && *cur != Sentinel) ++cur; + while (SizeType(cur - seq) < max && *cur != Sentinel) ++cur; fail_fast_assert(*cur == Sentinel); - return{ seq, cur - seq }; + return{ seq, SizeType(cur - seq) }; } @@ -96,7 +96,7 @@ array_view ensure_sentinel(const T* seq, SizeType max = std::n template inline basic_string_view ensure_z(T* const & sz, size_t max = std::numeric_limits::max()) { - return ensure_sentinel<0>(sz, max); + return ensure_sentinel(sz, max); } // TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation diff --git a/tests/string_view_tests.cpp b/tests/string_view_tests.cpp index fb57845..e553ccd 100644 --- a/tests/string_view_tests.cpp +++ b/tests/string_view_tests.cpp @@ -79,6 +79,14 @@ SUITE(string_view_tests) } } + TEST(TestConstructFromConstCharPointer) + { + const char* s = "Hello"; + cstring_view<> v = ensure_z(s); + CHECK(v.length() == 5); + CHECK(v.used_length() == v.length()); + } + TEST(TestConversionToConst) { char stack_string[] = "Hello"; From b39571781e4ce566de162cb187445b95b56cfd6f Mon Sep 17 00:00:00 2001 From: archshift Date: Mon, 2 Nov 2015 11:47:14 -0800 Subject: [PATCH 59/59] array_view: explicitly initialize constexpr function variables --- include/array_view.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/array_view.h b/include/array_view.h index 14d8888..69559f6 100644 --- a/include/array_view.h +++ b/include/array_view.h @@ -541,7 +541,7 @@ namespace details template 1), typename Ret = std::enable_if_t>> constexpr Ret shift_left(const index& other) noexcept { - Ret ret; + Ret ret{}; for (size_t i = 0; i < Rank - 1; ++i) { ret[i] = other[i + 1]; @@ -887,7 +887,7 @@ public: constexpr bounds_iterator& operator+=(difference_type n) noexcept { auto linear_idx = linearize(curr) + n; - std::remove_const_t stride; + std::remove_const_t stride = 0; stride[rank - 1] = 1; for (size_t i = rank - 1; i-- > 0;) {