mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
commit
05da162b37
21
.clang-format
Normal file
21
.clang-format
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
ColumnLimit: 100
|
||||||
|
|
||||||
|
UseTab: Never
|
||||||
|
IndentWidth: 4
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
NamespaceIndentation: Inner
|
||||||
|
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BreakConstructorInitializersBeforeComma: true
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
|
||||||
|
PointerAlignment: Left
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
|
||||||
|
SpaceAfterCStyleCast: true
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -1 +1,14 @@
|
|||||||
tests/unittest-cpp
|
tests/unittest-cpp
|
||||||
|
CMakeFiles
|
||||||
|
tests/CMakeFiles
|
||||||
|
tests/Debug
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
tests/*tests.dir
|
||||||
|
*.vcxproj
|
||||||
|
*.vcxproj.filters
|
||||||
|
*.sln
|
||||||
|
*.tlog
|
||||||
|
Testing/Temporary/*.*
|
||||||
|
CMakeCache.txt
|
||||||
|
*.suo
|
||||||
|
68
.travis.yml
Normal file
68
.travis.yml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# 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
|
||||||
|
- g++-5
|
||||||
|
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
|
@ -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(
|
include_directories(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
@ -8,4 +8,4 @@ include_directories(
|
|||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
@ -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.
|
[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
|
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.
|
a PR, please post a comment in the associated issue to avoid duplication of effort.
|
||||||
|
|
||||||
## Legal
|
## Legal
|
||||||
|
26
README.md
26
README.md
@ -1,9 +1,8 @@
|
|||||||
# 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) [![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
|
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:
|
This repo contains Microsoft's implementation of GSL.
|
||||||
[C++ Core Guidelines](https://github.com/Microsoft/CppCoreGuidelines).
|
|
||||||
|
|
||||||
The library includes types like `array_view<>`, `string_view<>`, `owner<>` and others.
|
The library includes types like `array_view<>`, `string_view<>`, `owner<>` and others.
|
||||||
|
|
||||||
@ -13,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.
|
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
|
> 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
|
# Quick Start
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
@ -25,16 +24,17 @@ The test suite that exercises GSL has been built and passes successfully on the
|
|||||||
* Windows using GCC 5.1
|
* Windows using GCC 5.1
|
||||||
* GNU/Linux using Clang/LLVM 3.6
|
* GNU/Linux using Clang/LLVM 3.6
|
||||||
* GNU/Linux using GCC 5.1
|
* GNU/Linux using GCC 5.1
|
||||||
* Mac OS Yosemite using XCode with AppleClang 7.0.0.7000072
|
* OS X Yosemite using Xcode with AppleClang 7.0.0.7000072
|
||||||
* Mac OS Yosemite using GCC-5.2.0
|
* 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
|
> 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.
|
contributing any changes that were necessary back to this project to benefit the wider community.
|
||||||
|
|
||||||
## Building the tests
|
## Building the tests
|
||||||
To build the tests, you will require the following:
|
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
|
* [UnitTest-cpp](https://github.com/Microsoft/unittest-cpp), to be cloned under the [tests/unittest-cpp](./tests/unittest-cpp) directory
|
||||||
of your GSL source.
|
of your GSL source.
|
||||||
|
|
||||||
@ -47,13 +47,13 @@ These steps assume the source code of this repository has been cloned into a dir
|
|||||||
cd build-x86
|
cd build-x86
|
||||||
|
|
||||||
2. Configure CMake to use the compiler of your choice (you can see a list by running `cmake --help`).
|
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
|
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).
|
3. Build the test suite (in this case, in the Debug configuration, Release is another good choice).
|
||||||
|
|
||||||
cmake --build . --config Debug
|
cmake --build . --config Debug
|
||||||
|
|
||||||
4. Run the test suite.
|
4. Run the test suite.
|
||||||
|
|
||||||
ctest -C Debug
|
ctest -C Debug
|
||||||
|
1286
include/array_view.h
1286
include/array_view.h
File diff suppressed because it is too large
Load Diff
@ -16,16 +16,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef GSL_FAIL_FAST_H
|
||||||
|
#define GSL_FAIL_FAST_H
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
namespace Guide
|
#if defined(GSL_THROWS_FOR_TESTING)
|
||||||
|
#include <stdexcept>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gsl
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
//
|
||||||
// Having "fail fast" result in an exception makes unit testing
|
// Having "fail fast" result in an exception makes unit testing
|
||||||
// the GSL classes that rely upon it much simpler.
|
// 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
|
struct fail_fast : public std::runtime_error
|
||||||
{
|
{
|
||||||
@ -41,6 +48,8 @@ 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) { if (!cond) std::terminate(); }
|
||||||
inline void fail_fast_assert(bool cond, const char* const) { 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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // GSL_FAIL_FAST_H
|
||||||
|
222
include/gsl.h
222
include/gsl.h
@ -16,11 +16,42 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef GSL_GSL_H
|
||||||
|
#define GSL_GSL_H
|
||||||
|
|
||||||
#include "array_view.h" // array_view, strided_array_view...
|
#include "array_view.h" // array_view, strided_array_view...
|
||||||
#include "string_view.h" // zstring, string_view, zstring_builder...
|
#include "string_view.h" // zstring, string_view, zstring_builder...
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Guide
|
#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
|
||||||
{
|
{
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -35,37 +66,41 @@ using owner = T;
|
|||||||
//
|
//
|
||||||
// GSL.assert: assertions
|
// GSL.assert: assertions
|
||||||
//
|
//
|
||||||
#define Expects(x) Guide::fail_fast_assert((x))
|
#define Expects(x) gsl::fail_fast_assert((x))
|
||||||
#define Ensures(x) Guide::fail_fast_assert((x))
|
#define Ensures(x) gsl::fail_fast_assert((x))
|
||||||
|
|
||||||
//
|
//
|
||||||
// GSL.util: utilities
|
// 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 F>
|
template <class F>
|
||||||
class Final_act
|
class final_act
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Final_act(F f) : f_(f) {}
|
explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {}
|
||||||
|
|
||||||
Final_act(const Final_act&& other) : f_(other.f_) {}
|
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(const final_act&) = delete;
|
||||||
Final_act& operator=(const Final_act&) = delete;
|
final_act& operator=(const final_act&) = delete;
|
||||||
|
|
||||||
~Final_act() { f_(); }
|
~final_act() noexcept { if (invoke_) f_(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
F f_;
|
F f_;
|
||||||
|
bool invoke_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// finally() - convenience function to generate a Final_act
|
// finally() - convenience function to generate a final_act
|
||||||
template <class F>
|
template <class F>
|
||||||
Final_act<F> finally(F f) { return Final_act<F>(f); }
|
final_act<F> finally(const F &f) noexcept { return final_act<F>(f); }
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
final_act<F> finally(F &&f) noexcept { return final_act<F>(std::forward<F>(f)); }
|
||||||
|
|
||||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
T narrow_cast(U u) { return static_cast<T>(u); }
|
T narrow_cast(U u) noexcept { return static_cast<T>(u); }
|
||||||
|
|
||||||
struct narrowing_error : public std::exception {};
|
struct narrowing_error : public std::exception {};
|
||||||
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
|
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
|
||||||
@ -102,23 +137,30 @@ typename Cont::value_type& at(Cont& cont, size_t index) { fail_fast_assert(index
|
|||||||
template<class T>
|
template<class T>
|
||||||
class not_null
|
class not_null
|
||||||
{
|
{
|
||||||
|
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
|
||||||
public:
|
public:
|
||||||
not_null(T t) : ptr_(t) { ensure_invariant(); }
|
not_null(T t) : ptr_(t) { ensure_invariant(); }
|
||||||
|
not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; }
|
||||||
// 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(const not_null &other) = default;
|
not_null(const not_null &other) = default;
|
||||||
|
not_null& operator=(const not_null &other) = default;
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||||
not_null(const not_null<U> &other) : ptr_(other.get())
|
not_null(const not_null<U> &other)
|
||||||
{
|
{
|
||||||
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<T>& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; }
|
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||||
|
not_null& operator=(const not_null<U> &other)
|
||||||
|
{
|
||||||
|
ptr_ = other.get();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// prevents compilation when someone attempts to assign a nullptr
|
// prevents compilation when someone attempts to assign a nullptr
|
||||||
|
not_null(std::nullptr_t) = delete;
|
||||||
|
not_null(int) = delete;
|
||||||
not_null<T>& operator=(std::nullptr_t) = delete;
|
not_null<T>& operator=(std::nullptr_t) = delete;
|
||||||
not_null<T>& operator=(int) = delete;
|
not_null<T>& operator=(int) = delete;
|
||||||
|
|
||||||
@ -153,135 +195,39 @@ private:
|
|||||||
not_null<T>& operator-=(size_t) = delete;
|
not_null<T>& operator-=(size_t) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace gsl
|
||||||
|
|
||||||
//
|
namespace std
|
||||||
// maybe_null
|
|
||||||
//
|
|
||||||
// Describes an optional pointer - provides symmetry with not_null
|
|
||||||
//
|
|
||||||
template<class T>
|
|
||||||
class maybe_null_dbg
|
|
||||||
{
|
{
|
||||||
public:
|
template<class T>
|
||||||
maybe_null_dbg() : ptr_(nullptr), tested_(false) {}
|
struct hash<gsl::not_null<T>>
|
||||||
|
|
||||||
maybe_null_dbg(const T& p) : ptr_(p), tested_(false) {}
|
|
||||||
maybe_null_dbg(const maybe_null_dbg& rhs) : ptr_(rhs.ptr_), tested_(false) {}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg(const not_null<U> &other) : ptr_(other.get()), tested_(false)
|
|
||||||
{
|
{
|
||||||
}
|
size_t operator()(const gsl::not_null<T> & value) const
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_dbg(const maybe_null_dbg<U> &other) : ptr_(other.get()), tested_(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
maybe_null_dbg& operator=(const T& p)
|
|
||||||
{
|
|
||||||
if (ptr_ != p)
|
|
||||||
{
|
{
|
||||||
ptr_ = p;
|
return hash<T>{}(value);
|
||||||
tested_ = false;
|
|
||||||
}
|
}
|
||||||
return *this;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
maybe_null_dbg& operator=(const maybe_null_dbg& rhs)
|
} // namespace std
|
||||||
{
|
|
||||||
if (this != &rhs)
|
|
||||||
{
|
|
||||||
ptr_ = rhs.ptr_;
|
|
||||||
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); }
|
|
||||||
|
|
||||||
T get() const {
|
|
||||||
fail_fast_assert(tested_);
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__assume(ptr_ != nullptr);
|
|
||||||
#endif
|
|
||||||
return ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T() const { return get(); }
|
#undef constexpr
|
||||||
T operator->() const { return get(); }
|
#pragma pop_macro("constexpr")
|
||||||
|
|
||||||
private:
|
#if _MSC_VER <= 1800
|
||||||
const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type
|
#pragma warning(pop)
|
||||||
|
|
||||||
// unwanted operators...pointers only point to single objects!
|
#ifndef GSL_THROWS_FOR_TESTING
|
||||||
// TODO ensure all arithmetic ops on this type are unavailable
|
#pragma undef noexcept
|
||||||
maybe_null_dbg<T>& operator++() = delete;
|
#endif // GSL_THROWS_FOR_TESTING
|
||||||
maybe_null_dbg<T>& operator--() = delete;
|
|
||||||
maybe_null_dbg<T> operator++(int) = delete;
|
|
||||||
maybe_null_dbg<T> operator--(int) = delete;
|
|
||||||
maybe_null_dbg<T>& operator+(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator+=(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator-(size_t) = delete;
|
|
||||||
maybe_null_dbg<T>& operator-=(size_t) = delete;
|
|
||||||
|
|
||||||
T ptr_;
|
#endif // _MSC_VER <= 1800
|
||||||
mutable bool tested_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
#endif // _MSC_VER
|
||||||
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(const maybe_null_ret& rhs) = default;
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
#if defined(GSL_THROWS_FOR_TESTING)
|
||||||
maybe_null_ret(const not_null<U> &other) : ptr_(other.get())
|
#undef noexcept
|
||||||
{
|
#endif // GSL_THROWS_FOR_TESTING
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
#endif // GSL_GSL_H
|
||||||
maybe_null_ret(const maybe_null_ret<U> &other) : ptr_(other.get())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
|
|
||||||
maybe_null_ret(const maybe_null_dbg<U> &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;
|
|
||||||
|
|
||||||
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<T>& operator++() = delete;
|
|
||||||
maybe_null_ret<T>& operator--() = delete;
|
|
||||||
maybe_null_ret<T> operator++(int) = delete;
|
|
||||||
maybe_null_ret<T> operator--(int) = delete;
|
|
||||||
maybe_null_ret<T>& operator+(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator+=(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator-(size_t) = delete;
|
|
||||||
maybe_null_ret<T>& operator-=(size_t) = delete;
|
|
||||||
|
|
||||||
const size_t ptee_size_ = sizeof(*ptr_); // T must be a pointer type
|
|
||||||
T ptr_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T> using maybe_null = maybe_null_ret<T>;
|
|
||||||
|
|
||||||
} // namespace Guide
|
|
||||||
|
@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef GSL_STRING_VIEW_H
|
||||||
|
#define GSL_STRING_VIEW_H
|
||||||
|
|
||||||
#include "array_view.h"
|
#include "array_view.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace Guide
|
namespace gsl
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// czstring and wzstring
|
// czstring and wzstring
|
||||||
@ -79,9 +82,9 @@ template<class T, class SizeType, const T Sentinel>
|
|||||||
array_view<T, dynamic_range> ensure_sentinel(const T* seq, SizeType max = std::numeric_limits<SizeType>::max())
|
array_view<T, dynamic_range> ensure_sentinel(const T* seq, SizeType max = std::numeric_limits<SizeType>::max())
|
||||||
{
|
{
|
||||||
auto cur = seq;
|
auto cur = seq;
|
||||||
while ((cur - seq) < max && *cur != Sentinel) ++cur;
|
while (SizeType(cur - seq) < max && *cur != Sentinel) ++cur;
|
||||||
fail_fast_assert(*cur == Sentinel);
|
fail_fast_assert(*cur == Sentinel);
|
||||||
return{ seq, cur - seq };
|
return{ seq, SizeType(cur - seq) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ array_view<T, dynamic_range> ensure_sentinel(const T* seq, SizeType max = std::n
|
|||||||
template<class T>
|
template<class T>
|
||||||
inline basic_string_view<T, dynamic_range> ensure_z(T* const & sz, size_t max = std::numeric_limits<size_t>::max())
|
inline basic_string_view<T, dynamic_range> ensure_z(T* const & sz, size_t max = std::numeric_limits<size_t>::max())
|
||||||
{
|
{
|
||||||
return ensure_sentinel<0>(sz, max);
|
return ensure_sentinel<T, size_t, 0>(sz, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation
|
// TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation
|
||||||
@ -134,7 +137,7 @@ basic_string_view<typename std::remove_pointer<typename Cont::pointer>::type, dy
|
|||||||
// to_string() allow (explicit) conversions from string_view to string
|
// to_string() allow (explicit) conversions from string_view to string
|
||||||
//
|
//
|
||||||
template<class CharT, size_t Extent>
|
template<class CharT, size_t Extent>
|
||||||
std::basic_string<typename std::remove_const<CharT>::type> to_string(const basic_string_view<CharT, Extent>& view)
|
std::basic_string<typename std::remove_const<CharT>::type> to_string(basic_string_view<CharT, Extent> view)
|
||||||
{
|
{
|
||||||
return{ view.data(), view.length() };
|
return{ view.data(), view.length() };
|
||||||
}
|
}
|
||||||
@ -161,7 +164,7 @@ public:
|
|||||||
size_type length() const { return sv_.length(); }
|
size_type length() const { return sv_.length(); }
|
||||||
|
|
||||||
pointer assume0() const { return data(); }
|
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 begin() const { return sv_.begin(); }
|
||||||
iterator end() const { return sv_.end(); }
|
iterator end() const { return sv_.end(); }
|
||||||
@ -176,3 +179,5 @@ using zstring_builder = basic_zstring_builder<char, Max>;
|
|||||||
template <size_t Max = dynamic_range>
|
template <size_t Max = dynamic_range>
|
||||||
using wzstring_builder = basic_zstring_builder<wchar_t, Max>;
|
using wzstring_builder = basic_zstring_builder<wchar_t, Max>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // GSL_STRING_VIEW_H
|
||||||
|
@ -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)
|
add_subdirectory(unittest-cpp)
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ include_directories(
|
|||||||
./unittest-cpp
|
./unittest-cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DSAFER_CPP_TESTING)
|
add_definitions(-DGSL_THROWS_FOR_TESTING)
|
||||||
|
|
||||||
if(MSVC14 OR MSVC12) # has the support we need
|
if(MSVC14 OR MSVC12) # has the support we need
|
||||||
# remove unnecessary warnings about unchecked iterators
|
# remove unnecessary warnings about unchecked iterators
|
||||||
@ -23,7 +23,7 @@ else()
|
|||||||
elseif(COMPILER_SUPPORTS_CXX11)
|
elseif(COMPILER_SUPPORTS_CXX11)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
else()
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -31,128 +31,23 @@ 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")
|
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()
|
endif()
|
||||||
|
|
||||||
add_executable(array_view_tests
|
function(add_gsl_test name)
|
||||||
array_view_tests.cpp
|
add_executable(${name} ${name}.cpp)
|
||||||
)
|
target_link_libraries(${name} UnitTest++)
|
||||||
target_link_libraries(array_view_tests
|
install(TARGETS ${name}
|
||||||
UnitTest++
|
RUNTIME DESTINATION bin
|
||||||
)
|
)
|
||||||
install(TARGETS array_view_tests
|
add_test(
|
||||||
RUNTIME DESTINATION bin
|
${name}
|
||||||
)
|
${name}
|
||||||
add_test(
|
)
|
||||||
NAME array_view_tests
|
endfunction()
|
||||||
COMMAND array_view_tests
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(string_view_tests
|
add_gsl_test(array_view_tests)
|
||||||
string_view_tests.cpp
|
add_gsl_test(string_view_tests)
|
||||||
)
|
add_gsl_test(at_tests)
|
||||||
target_link_libraries(string_view_tests
|
add_gsl_test(bounds_tests)
|
||||||
UnitTest++
|
add_gsl_test(notnull_tests)
|
||||||
)
|
add_gsl_test(assertion_tests)
|
||||||
install(TARGETS string_view_tests
|
add_gsl_test(utils_tests)
|
||||||
RUNTIME DESTINATION bin
|
add_gsl_test(owner_tests)
|
||||||
)
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
@ -16,18 +16,14 @@
|
|||||||
|
|
||||||
#include <UnitTest++/UnitTest++.h>
|
#include <UnitTest++/UnitTest++.h>
|
||||||
#include <array_view.h>
|
#include <array_view.h>
|
||||||
#include <numeric>
|
|
||||||
#include <array>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <functional>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -261,8 +257,8 @@ SUITE(array_view_tests)
|
|||||||
int a[30][4][5];
|
int a[30][4][5];
|
||||||
|
|
||||||
auto av = as_array_view(a);
|
auto av = as_array_view(a);
|
||||||
auto sub = av.section({15, 0, 0}, Guide::index<3>{2, 2, 2});
|
auto sub = av.section({15, 0, 0}, gsl::index<3>{2, 2, 2});
|
||||||
auto subsub = sub.section({1, 0, 0}, Guide::index<3>{1, 1, 1});
|
auto subsub = sub.section({1, 0, 0}, gsl::index<3>{1, 1, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(array_view_section)
|
TEST(array_view_section)
|
||||||
@ -554,7 +550,7 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
{
|
{
|
||||||
// zero stride
|
// zero stride
|
||||||
strided_array_view<int, 1> sav{ av, {{4}, {}} };
|
strided_array_view<int, 1> sav{ av,{ { 4 },{} } };
|
||||||
CHECK(sav[0] == 0);
|
CHECK(sav[0] == 0);
|
||||||
CHECK(sav[3] == 0);
|
CHECK(sav[3] == 0);
|
||||||
CHECK_THROW(sav[4], fail_fast);
|
CHECK_THROW(sav[4], fail_fast);
|
||||||
@ -562,7 +558,7 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
{
|
{
|
||||||
// zero extent
|
// zero extent
|
||||||
strided_array_view<int, 1> sav{ av,{ {},{1} } };
|
strided_array_view<int, 1> sav{ av,{ {},{ 1 } } };
|
||||||
CHECK_THROW(sav[0], fail_fast);
|
CHECK_THROW(sav[0], fail_fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,27 +631,17 @@ SUITE(array_view_tests)
|
|||||||
strided_array_view<int, 2> sav5{ av.as_array_view(dim<2>(), dim<2>()), { 1 } };
|
strided_array_view<int, 2> sav5{ av.as_array_view(dim<2>(), dim<2>()), { 1 } };
|
||||||
strided_array_view<int, 2> sav6{ av.as_array_view(dim<2>(), dim<2>()), { 1,1,1 } };
|
strided_array_view<int, 2> sav6{ av.as_array_view(dim<2>(), dim<2>()), { 1,1,1 } };
|
||||||
strided_array_view<int, 2> sav7{ av.as_array_view(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
|
strided_array_view<int, 2> sav7{ av.as_array_view(dim<2>(), dim<2>()), { { 1,1 },{ 1,1 },{ 1,1 } } };
|
||||||
}
|
|
||||||
#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<int, 1>{ arr, {1, {1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ arr, {{1,1 }, {1,1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {1, {1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 1>{ av, {{1,1 }, {1,1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast);
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast);
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
index<1> index{ 0, 1 };
|
||||||
|
strided_array_view<int, 1> sav8{ arr,{ 1,{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav9{ arr,{ { 1,1 },{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav10{ av,{ 1,{ 1,1 } } };
|
||||||
|
strided_array_view<int, 1> sav11{ av,{ { 1,1 },{ 1,1 } } };
|
||||||
|
strided_array_view<int, 2> sav12{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1 } } };
|
||||||
|
strided_array_view<int, 2> sav13{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } };
|
||||||
|
strided_array_view<int, 2> sav14{ av.as_array_view(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } };
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(strided_array_view_type_conversion)
|
TEST(strided_array_view_type_conversion)
|
||||||
@ -839,6 +825,94 @@ SUITE(array_view_tests)
|
|||||||
delete[] arr;
|
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)
|
TEST(index_operations)
|
||||||
{
|
{
|
||||||
size_t a[3] = { 0, 1, 2 };
|
size_t a[3] = { 0, 1, 2 };
|
||||||
@ -873,7 +947,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[0] == 0);
|
||||||
CHECK(i[1] == 1);
|
CHECK(i[1] == 1);
|
||||||
@ -914,11 +999,35 @@ SUITE(array_view_tests)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t check_sum = 0;
|
||||||
for (auto num : section)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
CHECK(num == av[idx][1]);
|
check_sum += av[i][1];
|
||||||
idx++;
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,7 +1098,7 @@ SUITE(array_view_tests)
|
|||||||
auto bounds = strided_bounds<1>({ length }, { 2 });
|
auto bounds = strided_bounds<1>({ length }, { 2 });
|
||||||
#else
|
#else
|
||||||
auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 });
|
auto bounds = strided_bounds<1>(index<1>{ length }, index<1>{ 2 });
|
||||||
#endif
|
#endif
|
||||||
strided_array_view<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
|
strided_array_view<int, 1> strided(&av.data()[1], av.size() - 1, bounds);
|
||||||
|
|
||||||
CHECK(strided.size() == length);
|
CHECK(strided.size() == length);
|
||||||
@ -1050,7 +1159,7 @@ SUITE(array_view_tests)
|
|||||||
for (unsigned int k = 0; k < section.extent<2>(); ++k)
|
for (unsigned int k = 0; k < section.extent<2>(); ++k)
|
||||||
{
|
{
|
||||||
auto idx = index<3>{ i,j,k }; // avoid braces in the CHECK macro
|
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,6 +1277,152 @@ SUITE(array_view_tests)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<size_t Rank, typename T1, typename T2>
|
||||||
|
index<Rank, T2> Convert(index<Rank, T1> 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{ std::numeric_limits<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{ std::numeric_limits<int>::max(), 1 };
|
||||||
|
index<2, long long> longlong_index{ big_int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == std::numeric_limits<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{ std::numeric_limits<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{ std::numeric_limits<int>::max() };
|
||||||
|
index<1, long long> longlong_index{ big_int_index };
|
||||||
|
|
||||||
|
CHECK(longlong_index[0] == std::numeric_limits<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)
|
TEST(constructors)
|
||||||
{
|
{
|
||||||
array_view<int, dynamic_range> av(nullptr);
|
array_view<int, dynamic_range> av(nullptr);
|
||||||
@ -1531,7 +1786,7 @@ SUITE(array_view_tests)
|
|||||||
CHECK_THROW(f(), fail_fast);
|
CHECK_THROW(f(), fail_fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AsWriteableBytes)
|
TEST(AsWriteableBytes)
|
||||||
{
|
{
|
||||||
int a[] = { 1, 2, 3, 4 };
|
int a[] = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
@ -1557,7 +1812,36 @@ SUITE(array_view_tests)
|
|||||||
CHECK(wav.data() == (byte*)&a[0]);
|
CHECK(wav.data() == (byte*)&a[0]);
|
||||||
CHECK(wav.length() == sizeof(a));
|
CHECK(wav.length() == sizeof(a));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NonConstIterator)
|
||||||
|
{
|
||||||
|
int a[] = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
|
{
|
||||||
|
array_view<int, dynamic_range> 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<int, dynamic_range> av = a;
|
||||||
|
for (auto& n : av)
|
||||||
|
{
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
CHECK(a[i] == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ArrayViewComparison)
|
TEST(ArrayViewComparison)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <UnitTest++/UnitTest++.h>
|
#include <UnitTest++/UnitTest++.h>
|
||||||
#include <gsl.h>
|
#include <gsl.h>
|
||||||
|
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
SUITE(assertion_tests)
|
SUITE(assertion_tests)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
SUITE(at_tests)
|
SUITE(at_tests)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Guide;;
|
using namespace gsl;;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -1,197 +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 <UnitTest++/UnitTest++.h>
|
|
||||||
#include <gsl.h>
|
|
||||||
|
|
||||||
using namespace Guide;
|
|
||||||
|
|
||||||
struct MyBase { bool foo() { return true; } };
|
|
||||||
struct MyDerived : public MyBase {};
|
|
||||||
struct Unrelated {};
|
|
||||||
|
|
||||||
SUITE(MaybeNullTests)
|
|
||||||
{
|
|
||||||
TEST(TestMaybeNull1)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null_dbg<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
bool threw = false;
|
|
||||||
|
|
||||||
CHECK_THROW(result = *opt_n, fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull2)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
if (opt_n.present())
|
|
||||||
result = *opt_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull3)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt_n(&n);
|
|
||||||
int result = 0;
|
|
||||||
if (opt_n != nullptr)
|
|
||||||
result = *opt_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test4_helper(maybe_null<int *> 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<int *> 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<int> o(n);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int g_int;
|
|
||||||
void test7_helper(maybe_null<maybe_null<int *> *> outptr)
|
|
||||||
{
|
|
||||||
g_int = 5;
|
|
||||||
|
|
||||||
if (outptr.present())
|
|
||||||
*outptr = &g_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test7b_helper(maybe_null_dbg<maybe_null_dbg<int *> *> outptr)
|
|
||||||
{
|
|
||||||
g_int = 5;
|
|
||||||
|
|
||||||
if (outptr.present())
|
|
||||||
*outptr = &g_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull7a)
|
|
||||||
{
|
|
||||||
maybe_null<int *> outval;
|
|
||||||
test7_helper(&outval);
|
|
||||||
CHECK(outval.present() && *outval == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull7b)
|
|
||||||
{
|
|
||||||
maybe_null_dbg<int *> outval;
|
|
||||||
test7b_helper(&outval);
|
|
||||||
CHECK_THROW((void)*outval, fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
int test8_helper1(maybe_null_dbg<int *> opt)
|
|
||||||
{
|
|
||||||
return *opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test8_helper2a(maybe_null_dbg<int *> opt)
|
|
||||||
{
|
|
||||||
if (!opt.present())
|
|
||||||
return 0;
|
|
||||||
return test8_helper1(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNull8a)
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null_dbg<int *> opt(&n);
|
|
||||||
CHECK_THROW(test8_helper2a(opt), fail_fast);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONVERT_TO_PTR_TO_CONST
|
|
||||||
int test9_helper(maybe_null<const int *> copt)
|
|
||||||
{
|
|
||||||
if (copt.present())
|
|
||||||
return *copt;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMaybeNull9()
|
|
||||||
{
|
|
||||||
int n = 5;
|
|
||||||
maybe_null<int *> opt(&n);
|
|
||||||
CHECK_THROW(test9_helper(opt), fail_fast);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST(TestMaybeNullCasting)
|
|
||||||
{
|
|
||||||
MyDerived derived;
|
|
||||||
maybe_null<MyDerived*> p = &derived;
|
|
||||||
CHECK(p.present());
|
|
||||||
|
|
||||||
maybe_null<MyBase*> q = p;
|
|
||||||
CHECK(q == p);
|
|
||||||
|
|
||||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
|
||||||
maybe_null<Unrelated*> r = p;
|
|
||||||
maybe_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
|
|
||||||
#endif
|
|
||||||
maybe_null_dbg<Unrelated*> t = reinterpret_cast<Unrelated*>(p.get());
|
|
||||||
|
|
||||||
CHECK_THROW((void)(void*)t.get(), fail_fast);
|
|
||||||
maybe_null_dbg<Unrelated*> u = reinterpret_cast<Unrelated*>(p.get());
|
|
||||||
CHECK(u.present());
|
|
||||||
CHECK((void*)p.get() == (void*)u.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestMaybeNullArrow)
|
|
||||||
{
|
|
||||||
MyDerived derived;
|
|
||||||
maybe_null_dbg<MyDerived*> p = &derived;
|
|
||||||
|
|
||||||
CHECK_THROW(p->foo(), fail_fast);
|
|
||||||
CHECK(p.present());
|
|
||||||
CHECK(p->foo());
|
|
||||||
|
|
||||||
maybe_null<MyBase*> q = p;
|
|
||||||
CHECK(q.present());
|
|
||||||
CHECK(q->foo());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int, const char *[])
|
|
||||||
{
|
|
||||||
return UnitTest::RunAllTests();
|
|
||||||
}
|
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
#include <UnitTest++/UnitTest++.h>
|
#include <UnitTest++/UnitTest++.h>
|
||||||
#include <gsl.h>
|
#include <gsl.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
struct MyBase {};
|
struct MyBase {};
|
||||||
struct MyDerived : public MyBase {};
|
struct MyDerived : public MyBase {};
|
||||||
@ -48,21 +49,35 @@ SUITE(NotNullTests)
|
|||||||
not_null<int*> p; // yay...does not compile!
|
not_null<int*> p; // yay...does not compile!
|
||||||
std::unique_ptr<int> up = std::make_unique<int>(120);
|
std::unique_ptr<int> up = std::make_unique<int>(120);
|
||||||
not_null<int*> p = up;
|
not_null<int*> p = up;
|
||||||
|
|
||||||
|
// Forbid non-nullptr assignable types
|
||||||
|
not_null<std::vector<int>> f(std::vector<int>{1});
|
||||||
|
not_null<int> z(10);
|
||||||
|
not_null<std::vector<int>> y({1,2});
|
||||||
#endif
|
#endif
|
||||||
int i = 12;
|
int i = 12;
|
||||||
auto rp = RefCounted<int>(&i);
|
auto rp = RefCounted<int>(&i);
|
||||||
not_null<int*> p(rp);
|
not_null<int*> p(rp);
|
||||||
CHECK(p.get() == &i);
|
CHECK(p.get() == &i);
|
||||||
|
|
||||||
|
not_null<std::shared_ptr<int>> x(std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TestNotNullCasting)
|
TEST(TestNotNullCasting)
|
||||||
{
|
{
|
||||||
MyDerived derived;
|
MyBase base;
|
||||||
|
MyDerived derived;
|
||||||
|
Unrelated unrelated;
|
||||||
|
not_null<Unrelated*> u = &unrelated;
|
||||||
not_null<MyDerived*> p = &derived;
|
not_null<MyDerived*> p = &derived;
|
||||||
not_null<MyBase*> q = p;
|
not_null<MyBase*> q = &base;
|
||||||
|
q = p; // allowed with heterogeneous copy ctor
|
||||||
CHECK(q == p);
|
CHECK(q == p);
|
||||||
|
|
||||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
#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<Unrelated*> r = p;
|
not_null<Unrelated*> r = p;
|
||||||
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
|
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <gsl.h>
|
#include <gsl.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
SUITE(owner_tests)
|
SUITE(owner_tests)
|
||||||
{
|
{
|
||||||
@ -33,6 +33,7 @@ SUITE(owner_tests)
|
|||||||
CHECK(*p == 120);
|
CHECK(*p == 120);
|
||||||
f(p);
|
f(p);
|
||||||
CHECK(*p == 121);
|
CHECK(*p == 121);
|
||||||
|
delete p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
SUITE(string_view_tests)
|
SUITE(string_view_tests)
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ SUITE(string_view_tests)
|
|||||||
|
|
||||||
TEST(TestConstructFromStdVector)
|
TEST(TestConstructFromStdVector)
|
||||||
{
|
{
|
||||||
std::vector<char> vec('h', 5);
|
std::vector<char> vec(5, 'h');
|
||||||
string_view<> v = vec;
|
string_view<> v = vec;
|
||||||
CHECK(v.length() == vec.size());
|
CHECK(v.length() == vec.size());
|
||||||
}
|
}
|
||||||
@ -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)
|
TEST(TestConversionToConst)
|
||||||
{
|
{
|
||||||
char stack_string[] = "Hello";
|
char stack_string[] = "Hello";
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <gsl.h>
|
#include <gsl.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace Guide;
|
using namespace gsl;
|
||||||
|
|
||||||
SUITE(utils_tests)
|
SUITE(utils_tests)
|
||||||
{
|
{
|
||||||
@ -37,6 +37,25 @@ SUITE(utils_tests)
|
|||||||
CHECK(i == 1);
|
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);
|
||||||
|
{
|
||||||
|
auto _2 = std::move(_1);
|
||||||
|
CHECK(i == 1);
|
||||||
|
}
|
||||||
|
CHECK(i == 1);
|
||||||
|
}
|
||||||
|
CHECK(i == 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(finally_function_with_bind)
|
TEST(finally_function_with_bind)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user