Compare commits

..

145 Commits

Author SHA1 Message Date
Herb Sutter 882720bd73 Changed default to per-TU violation handlers
And removed the feature test macro to instead tgest for a specific C++ version.
2021-01-27 16:36:59 -08:00
Herb Sutter 81c10b8017 normalize is a more accurate name than sanitize 2020-12-22 17:04:07 -08:00
Herb Sutter 0b80ac7d02 gsl/assert cleanup
Removed unnecessary headers
Added missing const
2020-12-19 12:58:31 -08:00
Herb Sutter e269976910 Added inline variable support 2020-12-18 13:16:40 -08:00
Herb Sutter 60beb7a363 Fixed the default
Accidentally flipped on the previous commit
2020-12-18 12:53:36 -08:00
Herb Sutter d5fc4efbf6 Turn off GCC bounds checking for the tests where we intentionally test out of bounds 2020-12-18 12:48:15 -08:00
Herb Sutter 25c0dee6e3 Reinstance the GSL_*_ON_CONTRACT_VIOLATION macros
At least the nonthrowing ones
2020-12-18 12:45:05 -08:00
Herb Sutter e02baff283 Remove minor code duplication 2020-12-18 12:34:07 -08:00
Herb Sutter 71fd73fa04 Make constructor more constinit-friendly 2020-12-18 12:27:33 -08:00
Herb Sutter c78ad8661c Added "vestigial" comments for downlevel feature test workarounds 2020-12-18 12:18:23 -08:00
Herb Sutter 070db845f8 Add -Wno-global-constructors for Clang 2020-12-18 12:10:36 -08:00
Herb Sutter 0c5a66b666 Added workaround for non-constexpr std::exchange 2020-12-18 12:02:42 -08:00
Herb Sutter 248a7cbdce Add feature test for literal constructor in downlevel compilers 2020-12-18 11:56:36 -08:00
Herb Sutter b77eaa87ee Make contract_group a literal type 2020-12-18 11:40:50 -08:00
Herb Sutter 9033021831 Removed stray .exchange 2020-12-18 11:34:25 -08:00
Herb Sutter a45265a75e Handler shouldn't be internally synchronized 2020-12-18 11:30:17 -08:00
Herb Sutter 8bd828744f Remove constexpr again to see what the failures were 2020-12-18 11:25:04 -08:00
Herb Sutter 1c37688ccd Replaced some of the previous workarounds with feature tests
As always with feature tests, they can only be used to aggressively adopt new features even before all compilers we need have the features -- the test lets us write a vestigial workaround for downllevel compilers, to be removed as soon as all compilers support the feature.
2020-12-18 11:20:03 -08:00
Herb Sutter 8dfd03feeb Remove constexpr from contract_group constructor 2020-12-17 13:19:29 -08:00
Herb Sutter d83e9ea05f Add workarounds for Android compiler and constexpr test 2020-12-17 12:11:42 -08:00
Herb Sutter 59f38376b9 Change auto to void to satisfy some compilers about definition ordering 2020-12-17 12:03:59 -08:00
Herb Sutter dd45e5cfbd Went back to old-style declaration for older compilers that don't do C++17 guaranteed copy elision
A concession to older compilers.
2020-12-17 11:58:53 -08:00
Herb Sutter 0cbb9e221d Removed double .load
Require `chandler` to be never null by installing `[]()noexcept{}` as the handler if given a null pointer.
This lets us remove the double test in `assertion`.
2020-12-17 11:36:23 -08:00
Herb Sutter b7548fd1cd Update multi_span
Revert changes in multi_span to avoid a merge conflict, since this file was deleted in a parallel PR
2020-12-17 10:35:34 -08:00
Herb Sutter cbfd8cd734 Parameterize Expects1 and Ensures` by contract group
Allows independently controlling handling of different categories of bugs, such as bounds checks vs. null checks.
User-extensible: Companies can instantiate their own `contract_group` objects for their own categories of contract checks, including for distinguishing contract "levels" like `Normal` vs. `Audit` by just creating those two groups that can then be controlled independently or in combination.
2020-11-27 17:06:01 -08:00
Herb Sutter c16e4ce59f Replace GSL_CONTRACT_CHECK with contract_group 2020-11-27 16:33:12 -08:00
Herb Sutter b34dc221a1 Remove GSL_ASSUME (unused code)
This is not specified in the C++ Core Guidelines as part of GSL, so it should not be documented or supported with a GSL name. And since we don't use it in the GSL repo either, we should just remove it directly. For more about why assumptions are a dangerous blunt instrument, including that they actively eliminate contracts checks including GSL's `Expects` and `Ensures`, see [P2064](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2064r0.pdf).
2020-11-27 11:10:53 -08:00
Herb Sutter c20a54c8e7 Remove __builtin_expect prediction assistance
In microbenchmarks I tried, using `__builtin_expect` to indicate which branch was likely/unlikely was never faster, and often slower, than just omitting. In GSL, this is used only for `Expects` and `Ensures` which are nearly always true, and all processors have long been great at predicting such branches well.
2020-11-27 11:07:55 -08:00
Jordan Maples [MSFT] 0140ab1d73 Change build status badges (#955)
Using Azure Pipelines badge instead of the Travis-ci and Appveyor badges.
2020-11-23 16:11:40 -08:00
hdf89shfdfs 475b785d2c Use CMAKE_CXX_STANDARD when available (#953)
* Use CMAKE_CXX_STANDARD when available

If the use has provided the variable CMAKE_CXX_STANDARD use that instead of providing a default cache variable.

* Typo
2020-11-16 14:05:33 -08:00
Jordan Maples [MSFT] 959ce58bbc Update gsl (#954) 2020-11-16 09:31:12 -08:00
Jordan Maples [MSFT] 804a14fe8b Update README.md
update the supported matrix
2020-11-11 13:52:11 -08:00
beinhaerter 00d4a5aab6 suppress bounds.1 (#950)
Suppress "warning C26481: Don't use pointer arithmetic. Use span instead (bounds.1)."

Co-authored-by: Werner Henze <werner.henze+gitcommits@posteo.de>
2020-11-11 13:47:58 -08:00
Jordan Maples [MSFT] 9150ce9a95 Adding std::hash<not_null<T>> tests to notnull_tests.cpp (#947)
* added std::hash<not_null> tests

* nl
2020-11-03 16:56:09 -08:00
Jordan Maples [MSFT] a150aaa4ed renaming main logic files. Added warning message of the removal and include passthrough. Renamed includes in the source files. Ran Clang-Format (#946)
Header rename
2020-10-29 17:38:48 -07:00
Jordan Maples [MSFT] e8978c01ab Remove deprecation of basic_zstring et al (#945)
* Azure pipeline (#8)

* azure-pipeline test

* nl @ eof

* trimming the pipeline and adding debug steps

* removing redundant lines

* change ctest to script cmd and remove debug

* removed bad char

* added dir change for ctest

* explicit output file and cmake standard

* test cat

* more ctest tests

* injecting failure in test for validation

* another test

* removing bad test

* massive matrix

* added parallel

* commenting everything but xcode out for testing purposes

* uncomment the other tests

* testing some variables

* rename

* changed macos versions

* adding one more layer of templates

* fixing jobs.yml

* idk what i'm doing

* slight modifications

* maybe some spaces will help

* removing 'variables.'

* another test

* adding back pr w/ autocancel

* adding failing test to validate error = failing task

* remove failing test

* trigger master

* nl in steps.yml

* removing deprecation of basic_zstring and derived types. only *string_span should have been deprecated
2020-10-29 11:34:05 -07:00
Jordan Maples [MSFT] 2c3ab0211c Fix C26481 warning in span array ctor (#944)
* Azure pipeline (#8)

* azure-pipeline test

* nl @ eof

* trimming the pipeline and adding debug steps

* removing redundant lines

* change ctest to script cmd and remove debug

* removed bad char

* added dir change for ctest

* explicit output file and cmake standard

* test cat

* more ctest tests

* injecting failure in test for validation

* another test

* removing bad test

* massive matrix

* added parallel

* commenting everything but xcode out for testing purposes

* uncomment the other tests

* testing some variables

* rename

* changed macos versions

* adding one more layer of templates

* fixing jobs.yml

* idk what i'm doing

* slight modifications

* maybe some spaces will help

* removing 'variables.'

* another test

* adding back pr w/ autocancel

* adding failing test to validate error = failing task

* remove failing test

* trigger master

* nl in steps.yml

* remove forced decay of array reference to pointer in span array ctor
2020-10-29 10:54:37 -07:00
Jordan Maples [MSFT] 179fba51f5 Azure pipeline (#8) (#943) 2020-10-28 16:35:49 -07:00
Jordan Maples [MSFT] d74ae54b60 Update README.md
Closes #911
2020-10-28 15:47:06 -07:00
bowie7070 b6c57e2403 Include gsl_narrow from gsl and fix comment. (#939)
narrow() is now in gsl_narrow rather than gsl_util. Include gsl_narrow when exceptions are enabled. Ensures that #include <gsl/gsl> includes entire library as advertised in the documentation.

Co-authored-by: Bowie Owens <bowie.owens@csiro.au>
2020-10-28 15:38:32 -07:00
mtnpke 736b62a838 Allow usage on platforms not providing iostreams (#935)
Closes #933.
2020-10-28 15:37:02 -07:00
Jordan Maples [MSFT] 6f4529395c Merge pull request #941 from JordanMaples/cmake_update
added GSL_ prefix to VS_ADD_NATIVE_VISUALIZERS
2020-10-26 10:12:40 -07:00
Jordan Maples [MSFT] 9fa2c5d5b9 Merge pull request #942 from tjs137/patch-1
use `narrow_cast`
2020-10-26 10:06:20 -07:00
tjs137 8009a703c2 use narrow_cast 2020-10-24 19:44:06 -04:00
Jordan Maples cfb4db0c1e added GSL_ prefix to VS_ADD_NATIVE_VISUALIZERS 2020-10-22 15:40:27 -07:00
Jordan Maples [MSFT] 6432f920ea Merge pull request #937 from beinhaerter/cast_warning
eliminate warning, use narrow_cast instead of static_cast
2020-10-20 10:55:05 -07:00
beinhaerter 2af9b11fe9 Update include/gsl/span
Co-authored-by: Jordan Maples [MSFT] <49793787+JordanMaples@users.noreply.github.com>
2020-10-20 00:44:11 +02:00
beinhaerter dc6fdff4c0 Update include/gsl/span
Co-authored-by: Jordan Maples [MSFT] <49793787+JordanMaples@users.noreply.github.com>
2020-10-20 00:44:02 +02:00
Werner Henze 2ccf36b4b9 eliminate warning, use narrow_cast instead of static_cast 2020-10-14 15:04:50 +02:00
Jordan Maples [MSFT] bd23bdc0ad Merge pull request #931 from JordanMaples/deprecate-string_span
Deprecate string_span
2020-10-02 12:36:09 -07:00
Jordan Maples 1665f07cf6 updating readme to reflect the deprecation of string_span 2020-10-01 14:38:41 -07:00
Jordan Maples 3f68a0034a fixed botched formatting 2020-10-01 14:16:01 -07:00
Jordan Maples 7721de88f3 ran clang-format over string_span 2020-10-01 14:08:01 -07:00
Jordan Maples a64c489c78 added deprecation message 2020-10-01 14:04:04 -07:00
Jordan Maples 5e773556fe initial deprecation of all types in string_span 2020-09-30 16:39:33 -07:00
Jordan Maples [MSFT] 5de956aaf0 Merge pull request #929 from JordanMaples/yml_experiment
split GitHub action into multiple files.
2020-09-23 14:23:52 -07:00
Jordan Maples [MSFT] bd803cc7cf Merge pull request #928 from JordanMaples/narrowing_error-add-what
add what to narrowing_error
2020-09-14 16:51:38 -07:00
Jordan Maples e7e3bf4f5f add what to narrowing_error 2020-09-14 15:50:46 -07:00
Jordan Maples [MSFT] 21b69e5cce Updating span section of Supported Features table.
Added a link to the span section to point to the "gsl::span and std::span" page in the wiki.
2020-08-28 10:53:19 -07:00
Jordan Maples [MSFT] d58e50c6f4 Merge pull request #922 from JordanMaples/constexpr-string_span
constexpr string_span
2020-08-27 14:29:30 -07:00
Jordan Maples 5fb0c8611e constexpr string_span stuff 2020-08-27 13:21:35 -07:00
Jordan Maples [MSFT] 6c518638ac Merge pull request #921 from JordanMaples/not_null-changes
not_null improvements
2020-08-26 17:48:26 -07:00
Jordan Maples 4a4bb3c13a adding changes suggested by Jonathan Wakely 2020-08-26 16:51:58 -07:00
Jordan Maples [MSFT] b6451c5db0 Merge pull request #920 from macjohnny/patch-1
fix typo in readme
2020-08-24 09:27:02 -07:00
Esteban Gehring 81957f6f91 fix typo in readme 2020-08-24 15:17:30 +02:00
Jordan Maples [MSFT] 6aa755e9ce Merge pull request #913 from jwakely/notnull_hash
Pass correct value to std::hash
2020-08-20 15:32:22 -07:00
Jordan Maples [MSFT] e426750695 Merge pull request #720 from menuet/fix-finally
Fix finally when passing a non const lvalue invokable thing
2020-08-17 09:10:50 -07:00
Pascal Menuet c25a7544b8 Fix finally with mutable lvalue invokable 2020-08-14 16:24:10 +02:00
Jordan Maples [MSFT] 06c46195ee Merge pull request #910 from JordanMaples/exception_fix_new_file
exception free - Version 2
2020-08-13 16:35:04 -07:00
Jordan Maples [MSFT] 83ce710d6c Merge pull request #807 from kuzkry/implemented_features
Add a table of features
2020-08-13 09:34:31 -07:00
Jordan Maples [MSFT] ec471abe44 Merge pull request #912 from jwakely/patch-1
Fix comment typos
2020-08-13 09:30:31 -07:00
Jordan Maples dad3d80c25 Update README.md
Rearranged and updated the table.
Added a second table of concepts that exist in the Microsoft GSL that do not exist in the C++ Core Guidelines
2020-08-13 15:35:46 +02:00
Krystian Kuzniarek a9ffcf7f65 add a table of features 2020-08-13 15:35:45 +02:00
Jonathan Wakely e09326eefd Pass correct value to std::hash 2020-08-13 12:59:01 +01:00
Jonathan Wakely d09f1544fd Fix comment typos 2020-08-13 10:46:39 +01:00
Jordan Maples 74968d3ef8 Merge branch 'master' into exception_fix_new_file 2020-08-12 17:14:13 -07:00
Jordan Maples [MSFT] 0c80f51f7c Merge pull request #908 from JordanMaples/fix_nodiscard_in_finally_macro
Finally [[nodiscard]] - Version 2
2020-08-12 15:49:55 -07:00
Jordan Maples [MSFT] ef714fa49e Merge pull request #676 from ericLemanissier/patch-3
fix requirement on not_null template
2020-08-12 15:28:25 -07:00
Jordan Maples [MSFT] 9355982fc5 Merge pull request #868 from mymedia2/master
Search for GoogleTest via pkg-config first
2020-08-12 15:08:54 -07:00
Jordan Maples 4da6a264c4 forgot newline at eof. 2020-08-12 13:22:33 -07:00
Jordan Maples 2469db7a5a add copyright header 2020-08-12 13:14:53 -07:00
Jordan Maples afe824490e change macro test to use __cplusplus instead of __has_cpp_attribute 2020-08-12 12:13:19 -07:00
Jordan Maples 72ddfb7a40 created new file for gsl_narrow, might want to rename if we go this approach to have all exception prone logic to live here 2020-08-11 17:11:14 -07:00
Jordan Maples bf0697be71 update readme to have the correct asset badges. This will render correctly when it's merged into the main repo 2020-08-11 16:46:41 -07:00
Jordan Maples 97cb97c685 readme update for the updated badges 2020-08-11 16:30:48 -07:00
Jordan Maples 13f57a1e70 update ci names 2020-08-11 16:28:37 -07:00
Jordan Maples c482c82d3a experimenting with splitting the yml files into their own runs 2020-08-11 16:08:16 -07:00
Jordan Maples 01eaf5bef1 macro version 2020-08-10 16:45:47 -07:00
Jordan Maples [MSFT] 63379b7935 Merge pull request #850 from beinhaerter/zstring_ctor
zstring_span: fix for Expects, simplify functions
2020-08-06 10:28:02 -07:00
Werner Henze 2231d733c6 zstring_span: fix for Expects, simplify functions
- `s[s.size() - 1]` is wrong for empty `s`, so `Expects(s.size() > 0)`
- no hard coded `'\0'`but `value_type{}`
- hard code `empty()` to return `false`
- simplify `as_string_span`: can never be `empty`
- clarify comment on `ensure_z`
2020-08-06 11:25:29 +02:00
Jordan Maples [MSFT] f8d9f2e2e3 Merge pull request #906 from TManhente/intel_suppress_fix
Fix  GSL_SUPPRESS definition on Intel C++ Compiler
2020-08-05 15:35:26 -07:00
Jordan Maples [MSFT] 552eedb390 Merge pull request #881 from robert-andrzejuk/patch-1
Refactor `narrow`.
2020-08-05 15:16:25 -07:00
Thiago M. de C. Marques ca3bf7710f Fix GSL_SUPPRESS definition on Intel C++ Compiler
Intel C++ Compiler defines the `_MSC_VER` macro, but it doesn't support `[[gsl::*]]` attributes.
2020-08-05 18:30:24 -03:00
Jordan Maples [MSFT] 559f8cfaae Merge pull request #899 from JordanMaples/dev/jomaples/cleanup_namespaces
cleanup gsl namespace qualification for dynamic_extent.
2020-07-15 14:56:54 -07:00
Jordan Maples [MSFT] f79ed1bb5c Merge pull request #876 from beinhaerter/make_notnull_noexcept
noexcept for make_(strict_)not_null and not_null comparisons
2020-07-15 14:36:17 -07:00
Jordan Maples [MSFT] bf6e103dfd Merge pull request #898 from JordanMaples/dev/jomaples/remove_pragma_push_pop
Remove msvc < 1910 checks.
2020-07-15 14:00:29 -07:00
Jordan Maples 4c66cea06c remove gsl namespace qualification within the gsl namespace 2020-07-15 13:11:57 -07:00
Jordan Maples 478d876951 remove pragma pop for constexpr macro 2020-07-15 11:43:29 -07:00
Jordan Maples 853b061141 remove msvc < 1910 checks as those versions are no longer supported. 2020-07-15 11:38:41 -07:00
Jordan Maples [MSFT] 301030310e Merge pull request #897 from microsoft/JordanMaples-patch-1
Update README.md
2020-07-07 10:58:04 -07:00
Jordan Maples [MSFT] be3bc0e754 Update README.md
Removed the line saying that specific workarounds exist for MSVC 2015 as they were removed in #886 when support for MSVC 2015 was dropped.
2020-07-06 08:22:35 -07:00
Jordan Maples [MSFT] 98002ab601 Merge pull request #893 from xvitaly/fix-noarch
Added ARCH_INDEPENDENT parameter to write_basic_package_version_file()
2020-06-10 11:09:31 -07:00
Vitaly Zaitsev cfe9baf02e Added ARCH_INDEPENDENT parameter to write_basic_package_version_file().
Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
2020-06-07 16:02:27 +02:00
Jordan Maples [MSFT] 0f6dbc9e29 Merge pull request #892 from JordanMaples/dev/jomaples/gsl3.1.0
Update project version to GSL 3.1.0
2020-06-04 10:10:04 -07:00
Jordan Maples 78744ed530 update cmake project version to reflect upcoming GSL 3.1.0 release 2020-06-03 16:52:20 -07:00
Jordan Maples [MSFT] 794d7bb69b Merge pull request #891 from JordanMaples/dev/jomaples/missing_span_ctad
Adding missing span deduction guides
2020-05-29 16:47:08 -07:00
Jordan Maples 72803a7ecb adding template type to the vector to suppress clang-10 warning that vector may not intend for type deduction. 2020-05-29 15:45:25 -07:00
Jordan Maples 4d2090ebc4 fixed typo 2020-05-29 10:54:13 -07:00
Jordan Maples c4a2ce6cc8 wrapping string_view checks in deduction guide checks to prevent 'macro unused' errors 2020-05-29 10:53:30 -07:00
Jordan Maples [MSFT] 9720cc552a Merge pull request #6 from CaseyCarter/deduction_guides
Add string_view test case and modify deduction guides
2020-05-29 10:16:06 -07:00
Casey Carter c143a07f61 Add string_view test case and modify deduction guides 2020-05-28 18:00:40 -07:00
Jordan Maples 6c405a1b7f adding a test to verify that the additional ctad works 2020-05-28 17:18:08 -07:00
Jordan Maples 689abc2982 adding container ctad 2020-05-28 14:04:31 -07:00
Jordan Maples [MSFT] 0dbdf322fa Merge pull request #886 from JordanMaples/dev/jomaples/build_matrix
compiler support revision
2020-05-26 15:14:08 -07:00
Jordan Maples [MSFT] 283e31478f Merge pull request #857 from pps83/master-natvis
Fix debugger visualizer for Ext=gsl::dynamic_extent
2020-05-21 11:32:45 -07:00
Jordan Maples [MSFT] 8cd19412b4 Merge pull request #887 from JordanMaples/dev/jomaples/p1976r2
gsl::span P1976R2 implemenation
2020-05-21 10:07:37 -07:00
Jordan Maples 25e7af9c7d fixing clang build break 2020-05-20 17:52:03 -07:00
Jordan Maples 7e4ed8da98 addressing Stephan's comments 2020-05-20 16:50:50 -07:00
Jordan Maples 34750814fb updating table with compiler versions that are in the test matrix 2020-05-20 16:24:05 -07:00
Jordan Maples 313a1121bf fix spacing 2020-05-20 15:46:20 -07:00
Jordan Maples 1e44481646 Finished integrating CaseyCarter's changes into span 2020-05-20 13:37:42 -07:00
Jordan Maples ed3fea6d93 implementing some of Casey's recommendations 2020-05-20 13:11:37 -07:00
Jordan Maples 31604f44f6 string_span_tests CLRF -> LF 2020-05-20 12:32:25 -07:00
Jordan Maples d3468230b1 renaming extent to prevent shadowing of static member 2020-05-20 12:29:56 -07:00
Jordan Maples 552cd20472 addressing most of Casey's comments 2020-05-20 10:59:57 -07:00
Jordan Maples 2085c7acde initial impl of P1976R2 2020-05-19 16:27:46 -07:00
Jordan Maples 33544a706e revised the readme 2020-05-13 17:05:45 -07:00
Jordan Maples f0160fcb1b removing breaking test code. removing compiler versions n-2 and beyond from travis script. Updating XCode 11.3 to 11.4 2020-05-13 14:49:17 -07:00
Jordan Maples [MSFT] 2a483c1728 Update span 2020-05-13 11:13:14 -07:00
Jordan Maples 031231466d pushing bad code that only reveals itself in gcc < 6 to test the allow_failures logic in travis 2020-05-13 11:04:11 -07:00
Jordan Maples a6d382109e missed a GSL_CONSTEXPR_NARROW for removal 2020-05-12 16:43:23 -07:00
Jordan Maples 09caa20d99 changing matrices and removing msc < 1910 work arounds 2020-05-12 16:21:55 -07:00
Jordan Maples [MSFT] 0843ea444f Merge pull request #884 from dipidoo/master
reflects verification of iOS and Android support
2020-05-08 09:57:45 -07:00
Bas Hendri 1e4e23738c updates README.md with iOS & Android support 2020-05-07 15:44:56 -07:00
Jordan Maples [MSFT] 839de21707 Merge pull request #879 from leha-bot/cmake/add-version-to-cmake-project
CMakeLists: add VERSION to project() and package
2020-05-06 16:57:50 -07:00
Bas Hendri 91858ca3f3 forces GTEST_HAS_DEATH_TEST 2020-05-04 13:31:08 -07:00
Bas Hendri 0ab350f5de enables iOS and Android testing 2020-05-04 13:26:50 -07:00
Robert Andrzejuk 84847041ee In narrow refactor !is_same_signedness to is_different_signedness 2020-04-29 20:39:44 +02:00
Robert Andrzejuk 1e5f44d3ea Refactor narrow - simplify & move is_same_signedness into function, remove uneeded detail namespace. Merge 2 if's with a ||. 2020-04-29 20:11:44 +02:00
leha-bot de053645bb CMakeLists: Drop ARCH_INDEPENDENT as it does not supported via old CMake 2020-04-28 13:07:41 +03:00
Werner Henze 29297e7dac noexcept for make_(strict_)not_null and not_null comparisons 2020-04-27 14:42:56 +02:00
Alex 879335cebf CMakeLists: add VERSION to project() and package
So the library consumers via find_package(Microsoft.GSL 3.0.2) could determine the actual library version.
2020-04-26 18:09:49 +03:00
Nicholas Guriev f5cf01083b Search for GoogleTest via pkg-config first 2020-04-18 13:30:17 +03:00
Pavel P 830b081de7 Fix debugger visualizer for Ext=gsl::dynamic_extent
VS 2019 doesn't seem to match -1 for size_t template parameter, as a result dynamic span/basic_string_span/basic_zstring_span show extent as `extent = 4294967295` (for 32-bit builds). This change updates details::extent_type to have static constexpr size_ parameter for non-dynamic span/basic_string_span/basic_zstring_span and simplifies/removes dynamic versions from GSL.natvis

fixes #856
2020-03-28 01:59:04 +06:00
ericLemanissier 423841e965 fix requirement on not_null template
it should be comparable to nullptr, it does not have to be assignable
2018-05-03 08:08:41 +02:00
40 changed files with 1780 additions and 1331 deletions
+50
View File
@@ -0,0 +1,50 @@
name: CI_Android
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
Android:
runs-on: macos-latest
defaults:
run:
working-directory: build
steps:
- uses: actions/checkout@v2
- name: Create build directory
run: mkdir -p build
working-directory: .
- name: Start emulator
run: |
echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-24;default;x86_64'
echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n xamarin_android_emulator -k 'system-images;android-24;default;x86_64' --force
$ANDROID_HOME/emulator/emulator -list-avds
echo "Starting emulator"
# Start emulator in background
nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot > /dev/null 2>&1 &
echo "Emulator starting"
- name: Configure
run: cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug ..
- name: Build
run: cmake --build . --parallel
- name: Wait for emulator ready
run: |
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 10; done; input keyevent 82'
$ANDROID_HOME/platform-tools/adb devices
$ANDROID_HOME/platform-tools/adb shell getprop ro.product.cpu.abi
echo "Emulator started"
- name: Deploy tests
run: |
adb push tests /data/local/tmp
adb shell find /data/local/tmp/tests -maxdepth 1 -exec chmod +x {} \\\;
- name: Test
run: adb shell find /data/local/tmp/tests -name "*_tests" -maxdepth 1 -exec {} \\\;
+51
View File
@@ -0,0 +1,51 @@
name: CI_iOS
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
iOS:
runs-on: macos-latest
defaults:
run:
working-directory: build
steps:
- uses: actions/checkout@v2
- name: Create build directory
run: mkdir -p build
working-directory: .
- name: Configure
run: |
cmake \
-GXcode \
-DCMAKE_SYSTEM_NAME=iOS \
"-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
-DCMAKE_OSX_DEPLOYMENT_TARGET=8 \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
"-DMACOSX_BUNDLE_GUI_IDENTIFIER=GSL.\$(EXECUTABLE_NAME)" \
-DMACOSX_BUNDLE_BUNDLE_VERSION=3.0.1 \
-DMACOSX_BUNDLE_SHORT_VERSION_STRING=3.0.1 \
..
- name: Build
run: cmake --build . --parallel `sysctl -n hw.ncpu` --config Release -- -sdk iphonesimulator
- name: Start simulator
run: |
RUNTIME=`xcrun simctl list runtimes iOS -j|jq '.runtimes|last.identifier'`
UDID=`xcrun simctl list devices iPhone available -j|jq -r ".devices[$RUNTIME]|last.udid"`
xcrun simctl bootstatus $UDID -b
- name: Test
run: |
for TEST in `find tests/Release-iphonesimulator -depth 1 -name "*.app"`
do
xcrun simctl install booted $TEST
TEST_ID=`plutil -convert json -o - $TEST/Info.plist|jq -r ".CFBundleIdentifier"`
xcrun simctl launch --console booted $TEST_ID
xcrun simctl uninstall booted $TEST_ID
done
+16 -230
View File
@@ -12,9 +12,9 @@ cache:
- ${TRAVIS_BUILD_DIR}/deps
stages:
- name: Latest # build jobs to run first and always
- name: Latest # Compiler with the latest major version
- name: Previous # Compilers with the major version Latest - 1
- name: Validation # run other jobs
- name: Legacy # build with all other supported compilers
jobs:
include:
@@ -62,73 +62,11 @@ jobs:
# AppleClang on OSX
##########################################################################
# Xcode 8.3
- name: AppleClang Xcode-8.3 C++14 Debug
stage: Legacy
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode8.3
- name: AppleClang Xcode-8.3 C++14 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
os: osx
osx_image: xcode8.3
# Xcode 9.0 earliest C++17 support
- name: AppleClang Xcode-9.0 C++17 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
os: osx
osx_image: xcode9 # AppleClang 9.1.0 same compiler in Xcode 9.0, 9.1 and 9.2
- name: AppleClang Xcode-9.0 C++17 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
os: osx
osx_image: xcode9
- name: AppleClang Xcode-9.0 C++14 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode9
- name: AppleClang Xcode-9.0 C++14 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
os: osx
osx_image: xcode9
# Xcode 9.4
- name: AppleClang Xcode-9.4 C++14 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode9.4 # AppleClang 9.1.0 same compiler as Xcode 9.3
- name: AppleClang Xcode-9.4 C++14 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
os: osx
osx_image: xcode9.4
- name: AppleClang Xcode-9.4 C++17 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
os: osx
osx_image: xcode9.4
- name: AppleClang Xcode-9.4 C++17 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
os: osx
osx_image: xcode9.4
# Xcode 10.1
- name: AppleClang Xcode-10.1 C++14 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode10.1 # AppleClang 10.0.0 same compiler as Xcode 10.0
- name: AppleClang Xcode-10.1 C++14 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
os: osx
osx_image: xcode10.1
- name: AppleClang Xcode-10.1 C++17 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
os: osx
osx_image: xcode10.1
- name: AppleClang Xcode-10.1 C++17 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
os: osx
osx_image: xcode10.1
# Xcode 10.3
- name: AppleClang Xcode-10.3 C++14 Debug
stage: Previous
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode10.3 # AppleClang 10.0.1 same compiler as Xcode 10.2
@@ -145,157 +83,33 @@ jobs:
os: osx
osx_image: xcode10.3
# Xcode 11.3
- name: AppleClang Xcode-11.3 C++17 Debug
# Xcode 11.4
- name: AppleClang Xcode-11.4 C++17 Debug
stage: Latest
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=17
os: osx
osx_image: xcode11.3 # AppleClang 11.0.0 linker update / same as Xcode 11.2
- name: AppleClang Xcode-11.3 C++17 Release
osx_image: xcode11.4
- name: AppleClang Xcode-11.4 C++17 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=17
os: osx
osx_image: xcode11.3
- name: AppleClang Xcode-11.3 C++14 Debug
osx_image: xcode11.4
- name: AppleClang Xcode-11.4 C++14 Debug
env: BUILD_TYPE=Debug GSL_CXX_STANDARD=14
os: osx
osx_image: xcode11.3
- name: AppleClang Xcode-11.3 C++14 Release
osx_image: xcode11.4
- name: AppleClang Xcode-11.4 C++14 Release
env: BUILD_TYPE=Release GSL_CXX_STANDARD=14
os: osx
osx_image: xcode11.3
osx_image: xcode11.4
##########################################################################
# Clang on Linux
##########################################################################
# Clang 3.6
- name: Clang-3.6 C++14 Debug
stage: Legacy
dist: xenial
env: CXX=clang++-3.6 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang36
apt:
packages:
- clang-3.6
- name: Clang-3.6 C++14 Release
dist: xenial
env: CXX=clang++-3.6 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang36
# Clang 3.7
- name: Clang-3.7 C++14 Debug
dist: xenial
env: CXX=clang++-3.7 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang37
apt:
packages:
- clang-3.7
- name: Clang-3.7 C++14 Release
dist: xenial
env: CXX=clang++-3.7 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang37
# Clang 3.8
- name: Clang-3.8 C++14 Debug
dist: xenial
env: CXX=clang++-3.8 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang38
apt:
packages:
- clang-3.8
- name: Clang-3.8 C++14 Release
dist: xenial
env: CXX=clang++-3.8 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang38
# Clang 3.9
- name: Clang-3.9 C++14 Debug
env: CXX=clang++-3.9 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang39
apt:
packages:
- clang-3.9
- name: Clang-3.9 C++14 Release
env: CXX=clang++-3.9 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang39
# Clang 4.0
- name: Clang-4.0 C++14 Debug
env: CXX=clang++-4.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang40
apt:
packages:
- clang-4.0
- name: Clang-4.0 C++14 Release
env: CXX=clang++-4.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang40
# Clang 5.0
- name: Clang-5.0 C++14 Debug
env: CXX=clang++-5.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang50
apt:
packages:
- clang-5.0
- name: Clang-5.0 C++14 Release
env: CXX=clang++-5.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang50
- name: Clang-5.0 C++17 Debug
env: CXX=clang++-5.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
addons: *clang50
- name: Clang 5.0 C++17 Release
env: CXX=clang++-5.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17
addons: *clang50
# Clang 6.0
- name: Clang-6.0 C++14 Debug
env: CXX=clang++-6.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang60
apt:
packages:
- clang-6.0
- name: Clang 6.0 C++14 Release
env: CXX=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang60
- name: Clang-6.0 C++17 Debug
env: CXX=clang++-6.0 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
addons: *clang60
- name: Clang 6.0 C++17 Release
env: CXX=clang++-6.0 BUILD_TYPE=Release GSL_CXX_STANDARD=17
addons: *clang60
# Clang 7 (default on Xenial and Bionic images)
- name: Clang-7 C++14 Debug
env: CXX=clang++ BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- name: Clang-7 C++14 Release
env: CXX=clang++ BUILD_TYPE=Release GSL_CXX_STANDARD=14
- name: Clang-7 C++17 Debug
env: CXX=clang++ BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- name: Clang-7 C++17 Release
env: CXX=clang++ BUILD_TYPE=Release GSL_CXX_STANDARD=17
# Clang 8
- name: Clang-8 C++14 Debug
env: CXX=clang++-8 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang8
apt:
sources:
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main'
key_url: https://apt.llvm.org/llvm-snapshot.gpg.key
packages:
- clang-8
- name: Clang-8 C++14 Release
env: CXX=clang++-8 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *clang8
- name: Clang-8 C++17 Debug
env: CXX=clang++-8 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
addons: *clang8
- name: Clang-8 C++17 Release
env: CXX=clang++-8 BUILD_TYPE=Release GSL_CXX_STANDARD=17
addons: *clang8
# Clang 9
- name: Clang-9 C++14 Debug
stage: Previous
env: CXX=clang++-9 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &clang9
apt:
@@ -339,37 +153,9 @@ jobs:
# GCC on Linux
##########################################################################
# GCC 5 (default on the Xenial image)
- name: GCC-5 C++14 Debug
stage: Legacy
dist: xenial
env: CXX=g++-5 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- name: GCC-5 C++14 Release
dist: xenial
env: CXX=g++-5 BUILD_TYPE=Release GSL_CXX_STANDARD=14
# GCC 6
- name: GCC-6 C++14 Debug
env: CXX=g++-6 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &gcc6
apt:
packages: g++-6
- name: GCC-6 C++14 Release
env: CXX=g++-6 BUILD_TYPE=Release GSL_CXX_STANDARD=14
addons: *gcc6
# GCC 7 (default on the Bionic image)
- name: GCC-7 C++14 Debug
env: CXX=g++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
- name: GCC-7 C++14 Release
env: CXX=g++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=14
- name: GCC-7 C++17 Debug
env: CXX=g++-7 BUILD_TYPE=Debug GSL_CXX_STANDARD=17
- name: GCC-7 C++17 Release
env: CXX=g++-7 BUILD_TYPE=Release GSL_CXX_STANDARD=17
# GCC 8
- name: GCC-8 C++14 Debug
stage: Previous
env: CXX=g++-8 BUILD_TYPE=Debug GSL_CXX_STANDARD=14
addons: &gcc8
apt:
@@ -538,7 +324,7 @@ before_script:
- |
cd "${TRAVIS_BUILD_DIR:?}"
mkdir build && cd build
if [[ ${GSL_CXX_STANDARD:-} ]]; then
if [[ ${GSL_CXX_STANDARD:-} ]]; then
CMAKE_GEN_FLAGS=("-DGSL_CXX_STANDARD=$GSL_CXX_STANDARD")
fi
CMAKE_GEN_FLAGS+=("-Wdev -Werror=dev --warn-uninitialized")
+49 -35
View File
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.1.3...3.16)
project(GSL CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(guidelineSupportLibrary)
project(GSL VERSION 3.1.0 LANGUAGES CXX)
include(ExternalProject)
find_package(Git)
@@ -8,39 +11,30 @@ find_package(Git)
# Use GNUInstallDirs to provide the right locations on all platforms
include(GNUInstallDirs)
# creates a library GSL which is an interface (header files only)
# Creates a library GSL which is an interface (header files only)
add_library(GSL INTERFACE)
# determine whether this is a standalone project or included by other projects
# NOTE: If you want to use GSL prefer to link against GSL using this alias target
# EX:
# target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL)
#
# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about
# whether GSL was added via `add_subdirectory` or `find_package`
add_library(Microsoft.GSL::GSL ALIAS GSL)
# Determine whether this is a standalone project or included by other projects
set(GSL_STANDALONE_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(GSL_STANDALONE_PROJECT ON)
endif ()
set(GSL_CXX_STANDARD "14" CACHE STRING "Use c++ standard")
set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}")
if (MSVC)
set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}")
else()
set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}")
set(GSL_STANDALONE_PROJECT ON)
endif()
# when minimum version required is 3.8.0 remove if below
# both branches do exactly the same thing
if (CMAKE_VERSION VERSION_LESS 3.7.9)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD)
# This GSL implementation generally assumes a platform that implements C++14 support.
set(gsl_min_cxx_standard "14")
if(COMPILER_SUPPORTS_CXX_STANDARD)
target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.")
endif()
else ()
target_compile_features(GSL INTERFACE "${GSL_CXX_STD}")
# on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
set(CMAKE_CXX_EXTENSIONS OFF)
if (GSL_STANDALONE_PROJECT)
gsl_set_default_cxx_standard(${gsl_min_cxx_standard})
else()
gsl_client_set_cxx_standard(${gsl_min_cxx_standard})
endif()
# add definitions to the library and targets that consume it
@@ -70,13 +64,13 @@ endif()
if (CMAKE_VERSION VERSION_GREATER 3.7.8)
if (MSVC_IDE)
option(VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
option(GSL_VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
else()
set(VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE)
set(GSL_VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE)
endif()
# add natvis file to the library so it will automatically be loaded into Visual Studio
if(VS_ADD_NATIVE_VISUALIZERS)
if(GSL_VS_ADD_NATIVE_VISUALIZERS)
target_sources(GSL INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/GSL.natvis>
)
@@ -92,12 +86,32 @@ install(
install(EXPORT Microsoft.GSLConfig NAMESPACE Microsoft.GSL:: DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
export(TARGETS GSL NAMESPACE Microsoft.GSL:: FILE Microsoft.GSLConfig.cmake)
# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about
# whether GSL was added via `add_subdirectory` or `find_package`
add_library(Microsoft.GSL::GSL ALIAS GSL)
# Add find_package() versioning support. The version for
# generated Microsoft.GSLConfigVersion.cmake will be used from
# last project() command. The version's compatibility is set between all
# minor versions (as it was in prev. GSL releases).
include(CMakePackageConfigHelpers)
if(${CMAKE_VERSION} VERSION_LESS "3.14.0")
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
else()
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT
)
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL)
option(GSL_TEST "Generate tests." ${GSL_STANDALONE_PROJECT})
if (GSL_TEST)
enable_testing()
add_subdirectory(tests)
enable_testing()
if(IOS)
add_compile_definitions(
GTEST_HAS_DEATH_TEST=1
)
endif()
add_subdirectory(tests)
endif ()
+6 -45
View File
@@ -19,9 +19,7 @@
</Expand>
</Type>
<!-- These types are from the span header. -->
<!-- This is for dynamic_extent spans. -->
<Type Name="gsl::span&lt;*, -1&gt;">
<Type Name="gsl::span&lt;*, *&gt;">
<DisplayString>{{ extent = {storage_.size_} }}</DisplayString>
<Expand>
<ArrayItems>
@@ -31,43 +29,7 @@
</Expand>
</Type>
<!-- This works for constexpr size spans. -->
<Type Name="gsl::span&lt;*, *&gt;">
<DisplayString>{{ extent = {extent} }}</DisplayString>
<Expand>
<ArrayItems>
<Size>extent</Size>
<ValuePointer>storage_.data_</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<!-- This is for dynamic_extent string_spans. -->
<Type Name="gsl::basic_string_span&lt;*, -1&gt;">
<DisplayString>{span_.storage_.data_,[span_.storage_.size_]na}</DisplayString>
<Expand>
<Item Name="[size]">span_.storage_.size_</Item>
<ArrayItems>
<Size>span_.storage_.size_</Size>
<ValuePointer>span_.storage_.data_</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<!-- This works for constexpr size string_spans. -->
<Type Name="gsl::basic_string_span&lt;*, *&gt;">
<DisplayString>{span_.storage_.data_,[span_.extent]na}</DisplayString>
<Expand>
<Item Name="[size]">span_.extent</Item>
<ArrayItems>
<Size>span_.extent</Size>
<ValuePointer>span_.storage_.data_</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<!-- This is for dynamic_extent zstring_spans. -->
<Type Name="gsl::basic_zstring_span&lt;*, -1&gt;">
<DisplayString>{span_.storage_.data_,[span_.storage_.size_]na}</DisplayString>
<Expand>
<Item Name="[size]">span_.storage_.size_</Item>
@@ -77,19 +39,18 @@
</ArrayItems>
</Expand>
</Type>
<!-- This works for constexpr size string_spans. -->
<Type Name="gsl::basic_zstring_span&lt;*, *&gt;">
<DisplayString>{span_.storage_.data_,[span_.extent]na}</DisplayString>
<DisplayString>{span_.storage_.data_,[span_.storage_.size_]na}</DisplayString>
<Expand>
<Item Name="[size]">span_.extent</Item>
<Item Name="[size]">span_.storage_.size_</Item>
<ArrayItems>
<Size>span_.extent</Size>
<Size>span_.storage_.size_</Size>
<ValuePointer>span_.storage_.data_</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<!-- These types are from the gsl header. -->
<Type Name="gsl::not_null&lt;*&gt;">
<!-- We can always dereference this since it's an invariant. -->
+90 -30
View File
@@ -1,12 +1,11 @@
# 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)
# GSL: Guidelines Support Library
[![Build Status](https://dev.azure.com/cppstat/GSL/_apis/build/status/microsoft.GSL?branchName=master)](https://dev.azure.com/cppstat/GSL/_build/latest?definitionId=1&branchName=master)
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.
The library includes types like `span<T>`, `string_span`, `owner<>` and others.
The entire implementation is provided inline in the headers under the [gsl](./include/gsl) directory. The implementation generally assumes a platform that implements C++14 support. There are specific workarounds to support MSVC 2015.
The entire implementation is provided inline in the headers under the [gsl](./include/gsl) directory. The implementation generally assumes a platform that implements C++14 support.
While some types have been broken out into their own headers (e.g. [gsl/span](./include/gsl/span)),
it is simplest to just include [gsl/gsl](./include/gsl/gsl) and gain access to the entire library.
@@ -20,35 +19,96 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
# Usage of Third Party Libraries
This project makes use of the [Google Test](https://github.com/google/googletest) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Google Test.
# Supported features
## Microsoft GSL implements the following from the C++ Core Guidelines:
Feature | Supported? | Description
-----------------------------------|:----------:|-------------
[**1. Views**][cg-views] | |
owner | &#x2611; | an alias for a raw pointer
not_null | &#x2611; | restricts a pointer / smart pointer to hold non-null values
span | &#x2611; | a view over a contiguous sequence of memory. Based on the standardized verison of `std::span`, however `gsl::span` enforces bounds checking. See the [wiki](https://github.com/microsoft/GSL/wiki/gsl::span-and-std::span) for additional information.
span_p | &#x2610; | spans a range starting from a pointer to the first place for which the predicate is true
basic_zstring | &#x2611; | A pointer to a C-string (zero-terminated array) with a templated char type
zstring | &#x2611; | An alias to `basic_zstring` with a char type of char
czstring | &#x2611; | An alias to `basic_zstring` with a char type of const char
wzstring | &#x2611; | An alias to `basic_zstring` with a char type of wchar_t
cwzstring | &#x2611; | An alias to `basic_zstring` with a char type of const wchar_t
u16zstring | &#x2611; | An alias to `basic_zstring` with a char type of char16_t
cu16zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char16_t
u32zstring | &#x2611; | An alias to `basic_zstring` with a char type of char32_t
cu32zstring | &#x2611; | An alias to `basic_zstring` with a char type of const char32_t
[**2. Owners**][cg-owners] | |
unique_ptr | &#x2611; | an alias to `std::unique_ptr`
shared_ptr | &#x2611; | an alias to `std::shared_ptr`
stack_array | &#x2610; | a stack-allocated array
dyn_array | &#x2610; | a heap-allocated array
[**3. Assertions**][cg-assertions] | |
Expects | &#x2611; | a precondition assertion; on failure it terminates by default if no user-installed handler
Ensures | &#x2611; | a postcondition assertion; on failure it terminates by default if no user-installed handler
[**4. Utilities**][cg-utilities] | |
move_owner | &#x2610; | a helper function that moves one `owner` to the other
byte | &#x2611; | either an alias to std::byte or a byte type
final_action | &#x2611; | a RAII style class that invokes a functor on its destruction
finally | &#x2611; | a helper function instantiating `final_action`
GSL_SUPPRESS | &#x2611; | a macro that takes an argument and turns it into `[[gsl::suppress(x)]]` or `[[gsl::suppress("x")]]`
[[implicit]] | &#x2610; | a "marker" to put on single-argument constructors to explicitly make them non-explicit
index | &#x2611; | a type to use for all container and array indexing (currently an alias for std::ptrdiff_t)
joining_thread | &#x2610; | a RAII style version of `std::thread` that joins
narrow | &#x2611; | a checked version of narrow_cast; it can throw `narrowing_error`
narrow_cast | &#x2611; | a narrowing cast for values and a synonym for static_cast
narrowing_error | &#x2611; | a custom exception type thrown by `narrow()`
[**5. Concepts**][cg-concepts] | &#x2610; |
## The following features do not exist in or have been removed from the C++ Core Guidelines:
Feature | Supported? | Description
-----------------------------------|:----------:|-------------
strict_not_null | &#x2611; | A stricter version of `not_null` with explicit constructors
multi_span | &#x2610; | Deprecated. Multi-dimensional span.
strided_span | &#x2610; | Deprecated. Support for this type has been discontinued.
basic_string_span | &#x2610; | Deprecated. Like `span` but for strings with a templated char type
string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of char
cstring_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of const char
wstring_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of wchar_t
cwstring_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of const wchar_t
u16string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of char16_t
cu16string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of const char16_t
u32string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of char32_t
cu32string_span | &#x2610; | Deprecated. An alias to `basic_string_span` with a char type of const char32_t
This is based on [CppCoreGuidelines semi-specification](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guidelines-support-library).
[cg-views]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslview-views
[cg-owners]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslowner-ownership-pointers
[cg-assertions]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslassert-assertions
[cg-utilities]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslutil-utilities
[cg-concepts]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslconcept-concepts
# Quick Start
## Supported Platforms
The test suite that exercises GSL has been built and passes successfully on the following platforms:<sup>1)</sup>
## Supported Compilers
The GSL officially supports the current and previous major release of MSVC, GCC, Clang, and XCode's Apple-Clang.
See our latest test results for the most up-to-date list of supported configurations.
* Windows using Visual Studio 2015
* Windows using Visual Studio 2017
* Windows using Clang/LLVM 3.6
* Windows using Clang/LLVM 7.0.0
* Windows using GCC 5.1
* Windows using Intel C++ Compiler 18.0
* GNU/Linux using Clang/LLVM 3.6-3.9
* GNU/Linux using Clang/LLVM 4.0
* GNU/Linux using Clang/LLVM 5.0
* GNU/Linux using Clang/LLVM 6.0
* GNU/Linux using Clang/LLVM 7.0
* GNU/Linux using GCC 5.1
* OS X Mojave 10.14.4 using Apple LLVM version 10.0.0 (10.0.1.10010046)
* OS X Mojave 10.14.3 using Apple LLVM version 10.0.0 (clang-1000.11.45.5)
* OS X Yosemite using Xcode with Apple Clang 7.0.0.7000072
* OS X Yosemite using GCC-5.2.0
* OS X Sierra 10.12.4 using Apple LLVM version 8.1.0 (Clang-802.0.42)
* OS X El Capitan (10.11) using Xcode with AppleClang 8.0.0.8000042
* OS X High Sierra 10.13.2 (17C88) using Apple LLVM version 9.0.0 (clang-900.0.39.2)
* FreeBSD 10.x with Clang/LLVM 3.6
Compiler |Toolset Versions Currently Tested
:------- |--:
XCode |11.4 & 10.3
GCC |9 & 8
Clang |11 & 10
Visual Studio with MSVC | VS2017 (15.9) & VS2019 (16.4)
Visual Studio with LLVM | VS2017 (Clang 9) & VS2019 (Clang 10)
> 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!
- Submit an issue specifying the platform and target.
- Consider contributing your changes by filing a pull request with any necessary changes.
- If at all possible, add a CI/CD step and add the button to the table below!
<sup>1)</sup> For `gsl::byte` to work correctly with Clang and GCC you might have to use the ` -fno-strict-aliasing` compiler option.
Target | CI/CD Status
:------- | -----------:
iOS | ![CI_iOS](https://github.com/microsoft/GSL/workflows/CI_iOS/badge.svg)
Android | ![CI_Android](https://github.com/microsoft/GSL/workflows/CI_Android/badge.svg)
Note: These CI/CD steps are run with each pull request, however failures in them are non-blocking.
## Building the tests
To build the tests, you will require the following:
@@ -65,7 +125,7 @@ These steps assume the source code of this repository has been cloned into a dir
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 15 2017" c:\GSL
3. Build the test suite (in this case, in the Debug configuration, Release is another good choice).
+5 -19
View File
@@ -9,7 +9,6 @@ configuration:
- Release
image:
- Visual Studio 2015
- Visual Studio 2017
- Visual Studio 2019
@@ -17,7 +16,6 @@ environment:
NINJA_TAG: v1.8.2
NINJA_SHA512: 9B9CE248240665FCD6404B989F3B3C27ED9682838225E6DC9B67B551774F251E4FF8A207504F941E7C811E7A8BE1945E7BCB94472A335EF15E23A0200A32E6D5
NINJA_PATH: C:\Tools\ninja\ninja-%NINJA_TAG%
VCVAR2015: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat'
VCVAR2017: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat'
VCVAR2019: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'
matrix:
@@ -34,14 +32,6 @@ environment:
USE_TOOLSET: LLVM
USE_GENERATOR: Ninja
matrix:
exclude:
- image: Visual Studio 2015
GSL_CXX_STANDARD: 17
- image: Visual Studio 2015
USE_TOOLSET: LLVM
USE_GENERATOR: MSBuild
cache:
- C:\cmake-3.14.4-win32-x86
- C:\Tools\ninja
@@ -72,9 +62,7 @@ before_build:
if ("$env:USE_GENERATOR" -eq "Ninja") {
$GeneratorFlags = '-k 10'
$Architecture = $env:PLATFORM
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2015") {
$env:VCVARSALL = "`"$env:VCVAR2015`" $Architecture"
} elseif ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
$env:VCVARSALL = "`"$env:VCVAR2017`" $Architecture"
} else {
$env:VCVARSALL = "`"$env:VCVAR2019`" $Architecture"
@@ -82,17 +70,15 @@ before_build:
$env:CMakeGenFlags = "-G Ninja -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD"
} else {
$GeneratorFlags = '/m /v:minimal'
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2015") {
$Generator = 'Visual Studio 14 2015'
} elseif ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
if ("$env:APPVEYOR_BUILD_WORKER_IMAGE" -eq "Visual Studio 2017") {
$Generator = 'Visual Studio 15 2017'
} else {
$Generator = 'Visual Studio 16 2019'
}
if ("$env:PLATFORM" -eq "x86") {
if ("$env:PLATFORM" -eq "x86") {
$Architecture = "Win32"
} else {
$Architecture = "x64"
} else {
$Architecture = "x64"
}
if ("$env:USE_TOOLSET" -eq "LLVM") {
$env:CMakeGenFlags = "-G `"$Generator`" -A $Architecture -T llvm -DGSL_CXX_STANDARD=$env:GSL_CXX_STANDARD"
+68
View File
@@ -0,0 +1,68 @@
trigger:
- master
pr:
autoCancel: true
# GCC
stages:
- stage: GCC
dependsOn: []
variables:
- name: CC
value: gcc
- name: CXX
value: g++
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate GCC latest'
imageName: ubuntu-20.04
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate GCC Previous'
imageName: ubuntu-18.04
# Clang
- stage: Clang
dependsOn: []
variables:
- name: CC
value: clang
- name: CXX
value: clang++
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Clang latest'
imageName: ubuntu-20.04
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Clang Previous'
imageName: ubuntu-18.04
# MSVC
- stage: MSVC
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate MSVC latest'
imageName: windows-latest
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate MSVC Previous'
imageName: vs2017-win2016
# Apple-Clang
- stage: Apple_Clang
dependsOn: []
jobs:
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Apple-Clang latest'
imageName: macos-10.15
- template: ./pipelines/jobs.yml
parameters:
jobName: 'Validate Apple-Clang Previous'
imageName: macos-10.14
+61
View File
@@ -0,0 +1,61 @@
# This cmake module is meant to hold helper functions/macros
# that make maintaining the cmake build system much easier.
# This is especially helpful since gsl needs to provide coverage
# for multiple versions of cmake.
#
# Any functions/macros should have a gsl_* prefix to avoid problems
if (DEFINED guideline_support_library_include_guard)
return()
endif()
set(guideline_support_library_include_guard ON)
function(gsl_set_default_cxx_standard min_cxx_standard)
set(GSL_CXX_STANDARD "${min_cxx_standard}" CACHE STRING "Use c++ standard")
set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}")
if (MSVC)
set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}")
else()
set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}")
endif()
# when minimum version required is 3.8.0 remove if below
# both branches do exactly the same thing
if (CMAKE_VERSION VERSION_LESS 3.7.9)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD)
if(COMPILER_SUPPORTS_CXX_STANDARD)
target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.")
endif()
else()
target_compile_features(GSL INTERFACE "${GSL_CXX_STD}")
# on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
endfunction()
# The best way for a project to specify the GSL's C++ standard is by the client specifying
# the CMAKE_CXX_STANDARD. However, this isn't always ideal. Since the CMAKE_CXX_STANDARD is
# tied to the cmake version. And many projects have low cmake minimums.
#
# So provide an alternative approach in case that doesn't work.
function(gsl_client_set_cxx_standard min_cxx_standard)
if (DEFINED CMAKE_CXX_STANDARD)
if (${CMAKE_CXX_STANDARD} VERSION_LESS ${min_cxx_standard})
message(FATAL_ERROR "GSL: Requires at least CXX standard ${min_cxx_standard}, user provided ${CMAKE_CXX_STANDARD}")
endif()
# Set the GSL standard to what the client desires
set(GSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}" PARENT_SCOPE)
# Exit out early to avoid extra unneccessary work
return()
endif()
# Otherwise pick a reasonable default
gsl_set_default_cxx_standard(${min_cxx_standard})
endfunction()
+63
View File
@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
#include <gsl/assert> // for contracts
#include <gsl/span> // for dynamic_extent, span
#include <algorithm> // for copy_n
#include <cstddef> // for ptrdiff_t
#include <type_traits> // for is_assignable
#ifdef _MSC_VER
#pragma warning(push)
// turn off some warnings that are noisy about our contract checks
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // unsafe use of std::copy_n
#endif // _MSC_VER
namespace gsl
{
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
template <class SrcElementType, std::size_t SrcExtent, class DestElementType,
std::size_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
"Elements of source span can not be assigned to elements of destination span");
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
(SrcExtent <= DestExtent),
"Source range is longer than target range");
Expects(dest.size() >= src.size(), Bounds);
// clang-format off
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
// clang-format on
std::copy_n(src.data(), src.size(), dest.data());
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_ALGORITHM_H
+149
View File
@@ -0,0 +1,149 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
//
// Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif // defined(__clang__)
#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
// !_HAS_EXCEPTIONS))
#include <exception>
#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
// !_HAS_EXCEPTIONS))
//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
//
// GSL.assert: assertions
//
namespace gsl
{
namespace details
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
typedef void(__cdecl* terminate_handler)();
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
// clang-format on
[[noreturn]] inline void __cdecl default_terminate_handler()
{
__fastfail(RANGE_CHECKS_FAILURE);
}
inline gsl::details::terminate_handler& get_terminate_handler() noexcept
{
static terminate_handler handler = &default_terminate_handler;
return handler;
}
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
[[noreturn]] inline void terminate() noexcept
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
(*gsl::details::get_terminate_handler())();
#else
std::terminate();
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
}
} // namespace details
class contract_group {
public:
#if defined __cpp_noexcept_function_type
using handler = void (*)() noexcept;
#else // VESTIGIAL, remove when no longer needed for downlevel compilers
using handler = void (*)();
#endif
constexpr contract_group (handler h = nullptr) : chandler(normalize(h)) { }
constexpr auto set_handler(handler h) -> handler { auto old = chandler; chandler = normalize(h); return old; }
constexpr auto get_handler() const -> handler { return chandler; }
constexpr auto expects (bool b) -> void { assertion(b); }
constexpr auto ensures (bool b) -> void { assertion(b); }
private:
constexpr auto assertion(bool b) -> void { if (!b) chandler(); }
constexpr auto normalize(handler h) -> handler { return h ? h : []()noexcept{}; }
handler chandler;
};
// By default, there is one violation handler per translation unit.
// Defining GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS and compiling as
// C++17 (or later) opts into using a global violation handler.
#if defined GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS && __cplusplus >= 201703L
#define GSL_CONTRACT_VIOLATION_GRANULARITY inline
#else
#define GSL_CONTRACT_VIOLATION_GRANULARITY static
#endif
auto GSL_CONTRACT_VIOLATION_GRANULARITY Default = contract_group(
#if defined GSL_UNENFORCED_ON_CONTRACT_VIOLATION
// use default == null handler
#else // if defined GSL_TERMINATE_ON_CONTRACT_VIOLATION
&gsl::details::terminate
#endif
);
auto GSL_CONTRACT_VIOLATION_GRANULARITY Bounds = Default;
auto GSL_CONTRACT_VIOLATION_GRANULARITY Null = Default;
auto GSL_CONTRACT_VIOLATION_GRANULARITY Testing = Default;
} // namespace gsl
#define Expects(cond, kind) kind.expects(cond)
#define Ensures(cond, kind) kind.ensures(cond)
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // GSL_CONTRACTS_H
+213
View File
@@ -0,0 +1,213 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
//
// make suppress attributes work for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#include <type_traits>
// VS2017 15.8 added support for the __cpp_lib_byte definition
// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
#ifdef _MSC_VER
#pragma warning(push)
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates
// does not always work
#ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \
(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 1
#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
// 201603)
#define GSL_USE_STD_BYTE 0
#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
// 201603)
#endif // GSL_USE_STD_BYTE
#else // _MSC_VER
#ifndef GSL_USE_STD_BYTE
#include <cstddef> /* __cpp_lib_byte */
// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte
// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 1
#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 0
#endif // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#endif // GSL_USE_STD_BYTE
#endif // _MSC_VER
// Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__
#define byte_may_alias
#endif // defined __clang__ || defined __GNUC__
#if GSL_USE_STD_BYTE
#include <cstddef>
#endif
namespace gsl
{
#if GSL_USE_STD_BYTE
using std::byte;
using std::to_integer;
#else // GSL_USE_STD_BYTE
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte_may_alias byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return static_cast<IntegerType>(b);
}
#endif // GSL_USE_STD_BYTE
template <bool E, typename T>
constexpr byte to_byte_impl(T t) noexcept
{
static_assert(
E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
return static_cast<byte>(t);
}
template <>
// NOTE: need suppression since c++14 does not allow "return {t}"
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{
return byte(t);
}
template <typename T>
constexpr byte to_byte(T t) noexcept
{
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}
template <int I>
constexpr byte to_byte() noexcept
{
static_assert(I >= 0 && I <= 255,
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
return static_cast<byte>(I);
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_BYTE_H
+12 -8
View File
@@ -17,13 +17,17 @@
#ifndef GSL_GSL_H
#define GSL_GSL_H
#include <gsl/gsl_algorithm> // copy
#include <gsl/gsl_assert> // Ensures/Expects
#include <gsl/gsl_byte> // byte
#include <gsl/gsl_util> // finally()/narrow()/narrow_cast()...
#include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/pointers> // owner, not_null
#include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder...
#include <gsl/algorithm> // copy
#include <gsl/assert> // contracts
#include <gsl/byte> // byte
#include <gsl/pointers> // owner, not_null
#include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder...
#include <gsl/util> // finally()/narrow_cast()...
#ifdef __cpp_exceptions
#include <gsl/narrow> // narrow()
#endif
#endif // GSL_GSL_H
+3 -61
View File
@@ -1,61 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_ALGORITHM_H
#define GSL_ALGORITHM_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/span> // for dynamic_extent, span
#include <algorithm> // for copy_n
#include <cstddef> // for ptrdiff_t
#include <type_traits> // for is_assignable
#ifdef _MSC_VER
#pragma warning(push)
// turn off some warnings that are noisy about our Expects statements
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // unsafe use of std::copy_n
#endif // _MSC_VER
namespace gsl
{
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
template <class SrcElementType, std::size_t SrcExtent, class DestElementType,
std::size_t DestExtent>
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
{
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
"Elements of source span can not be assigned to elements of destination span");
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
(SrcExtent <= DestExtent),
"Source range is longer than target range");
Expects(dest.size() >= src.size());
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
std::copy_n(src.data(), src.size(), dest.data());
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_ALGORITHM_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
#include <gsl/algorithm>
+3 -133
View File
@@ -1,133 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
//
// Temporary until MSVC STL supports no-exceptions mode.
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>
#define RANGE_CHECKS_FAILURE 0
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-noreturn"
#endif // defined(__clang__)
#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#include <exception>
#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
//
// make suppress attributes parse for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
#if defined(__clang__) || defined(__GNUC__)
#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define GSL_LIKELY(x) (!!(x))
#define GSL_UNLIKELY(x) (!!(x))
#endif // defined(__clang__) || defined(__GNUC__)
//
// GSL_ASSUME(cond)
//
// Tell the optimizer that the predicate cond must hold. It is unspecified
// whether or not cond is actually evaluated.
//
#ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond)
#elif defined(__GNUC__)
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
#else
#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
#endif
//
// GSL.assert: assertions
//
namespace gsl
{
namespace details
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
typedef void(__cdecl* terminate_handler)();
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
// clang-format on
[[noreturn]] inline void __cdecl default_terminate_handler()
{
__fastfail(RANGE_CHECKS_FAILURE);
}
inline gsl::details::terminate_handler& get_terminate_handler() noexcept
{
static terminate_handler handler = &default_terminate_handler;
return handler;
}
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
[[noreturn]] inline void terminate() noexcept
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
(*gsl::details::get_terminate_handler())();
#else
std::terminate();
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
}
} // namespace details
} // namespace gsl
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // GSL_CONTRACTS_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/assert> instead of <gsl/gsl_assert>")
#include <gsl/assert>
+3 -209
View File
@@ -1,209 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
//
// make suppress attributes work for some compilers
// Hopefully temporary until suppression standardization occurs
//
#if defined(__clang__)
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
#else
#if defined(_MSC_VER)
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
#else
#define GSL_SUPPRESS(x)
#endif // _MSC_VER
#endif // __clang__
#include <type_traits>
// VS2017 15.8 added support for the __cpp_lib_byte definition
// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
#ifdef _MSC_VER
#pragma warning(push)
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work
#ifndef GSL_USE_STD_BYTE
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 1
#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#define GSL_USE_STD_BYTE 0
#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
#endif // GSL_USE_STD_BYTE
#else // _MSC_VER
#ifndef GSL_USE_STD_BYTE
#include <cstddef> /* __cpp_lib_byte */
// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
// also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 1
#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#define GSL_USE_STD_BYTE 0
#endif //defined(__cplusplus) && (__cplusplus >= 201703L) &&
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
#endif // GSL_USE_STD_BYTE
#endif // _MSC_VER
// Use __may_alias__ attribute on gcc and clang
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
#define byte_may_alias __attribute__((__may_alias__))
#else // defined __clang__ || defined __GNUC__
#define byte_may_alias
#endif // defined __clang__ || defined __GNUC__
#if GSL_USE_STD_BYTE
#include <cstddef>
#endif
namespace gsl
{
#if GSL_USE_STD_BYTE
using std::byte;
using std::to_integer;
#else // GSL_USE_STD_BYTE
// This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant
enum class byte_may_alias byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>>(byte b, IntegerType shift) noexcept
{
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept
{
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator^(byte l, byte r) noexcept
{
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return static_cast<IntegerType>(b);
}
#endif // GSL_USE_STD_BYTE
template <bool E, typename T>
constexpr byte to_byte_impl(T t) noexcept
{
static_assert(
E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
return static_cast<byte>(t);
}
template <>
// NOTE: need suppression since c++14 does not allow "return {t}"
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
{
return byte(t);
}
template <typename T>
constexpr byte to_byte(T t) noexcept
{
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
}
template <int I>
constexpr byte to_byte() noexcept
{
static_assert(I >= 0 && I <= 255,
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
return static_cast<byte>(I);
}
} // namespace gsl
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_BYTE_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/byte> instead of <gsl/gsl_byte>")
#include <gsl/byte>
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/narrow> instead of <gsl/gsl_narrow>")
#include <gsl/narrow>
+3 -171
View File
@@ -1,171 +1,3 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
#include <gsl/gsl_assert> // for Expects
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
#include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif // _MSC_VER < 1910
#endif // _MSC_VER
#if (defined(_MSC_VER) && _MSC_VER < 1910) || (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 6)
#define GSL_CONSTEXPR_NARROW 0
#else
#define GSL_CONSTEXPR_NARROW 1
#endif
namespace gsl
{
//
// GSL.util: utilities
//
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;
// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
explicit final_action(F f) noexcept : f_(std::move(f)) {}
final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {}
final_action(const final_action&) = delete;
final_action& operator=(const final_action&) = delete;
final_action& operator=(final_action&&) = delete;
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
~final_action() noexcept
{
if (invoke_) f_();
}
private:
F f_;
bool invoke_{true};
};
// finally() - convenience function to generate a final_action
template <class F>
final_action<F> finally(const F& f) noexcept
{
return final_action<F>(f);
}
template <class F>
final_action<F> finally(F&& f) noexcept
{
return final_action<F>(std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
struct narrowing_error : public std::exception
{
};
namespace details
{
template <class T, class U>
struct is_same_signedness
: public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
{
};
} // namespace details
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
#if GSL_CONSTEXPR_NARROW
constexpr
#endif
T narrow(U u) noexcept(false)
{
T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u) throw narrowing_error{};
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
throw narrowing_error{};
return t;
}
//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N));
return arr[narrow_cast<std::size_t>(i)];
}
template <class Cont>
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
using size_type = decltype(cont.size());
return cont[narrow_cast<size_type>(i)];
}
template <class T>
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
return *(cont.begin() + i);
}
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_UTIL_H
#pragma once
#pragma message("This header will soon be removed. Use <gsl/util> instead of <gsl/gsl_util>")
#include <gsl/util>
+177 -71
View File
@@ -17,12 +17,12 @@
#ifndef GSL_MULTI_SPAN_H
#define GSL_MULTI_SPAN_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/assert> // for Expects
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <algorithm> // for transform, lexicographical_compare
#include <array> // for array
#include <algorithm> // for transform, lexicographical_compare
#include <array> // for array
#include <cstddef> // for std::ptrdiff_t, size_t, nullptr_t
#include <cstdint> // for PTRDIFF_MAX
#include <functional> // for divides, multiplies, minus, negate, plus
@@ -50,11 +50,6 @@
#pragma warning(disable : 26465) // TODO: bug - suppression does not work on template functions
#pragma warning(disable : 4996) // use of function or classes marked [[deprecated]]
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif // _MSC_VER < 1910
#endif // _MSC_VER
#if defined(__GNUC__) || defined(__clang__)
@@ -100,7 +95,8 @@ namespace details
} // namespace details
template <std::size_t Rank>
class [[deprecated]] multi_span_index final {
class [[deprecated]] multi_span_index final
{
static_assert(Rank > 0, "Rank must be greater than 0!");
template <std::size_t OtherRank>
@@ -115,10 +111,12 @@ public:
constexpr multi_span_index() noexcept {}
constexpr multi_span_index(const value_type(&values)[Rank]) noexcept
constexpr multi_span_index(const value_type (&values)[Rank]) noexcept
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::copy(values, values + Rank, elems);
}
@@ -132,8 +130,10 @@ public:
constexpr multi_span_index& operator=(const multi_span_index& rhs) noexcept = default;
// Preconditions: component_idx < rank
// clang-format off
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](std::size_t component_idx)
{
Expects(component_idx < Rank); // Component index must be less than rank
@@ -141,16 +141,20 @@ public:
}
// Preconditions: component_idx < rank
// clang-format off
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr const_reference operator[](std::size_t component_idx) const
{
Expects(component_idx < Rank); // Component index must be less than rank
return elems[component_idx];
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
constexpr bool operator==(const multi_span_index& rhs) const
{
return std::equal(elems, elems + rank, rhs.elems);
@@ -183,16 +187,20 @@ public:
constexpr multi_span_index& operator+=(const multi_span_index& rhs)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, rhs.elems, elems, std::plus<value_type>{});
return *this;
}
constexpr multi_span_index& operator-=(const multi_span_index& rhs)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, rhs.elems, elems, std::minus<value_type>{});
return *this;
}
@@ -218,8 +226,10 @@ public:
constexpr multi_span_index& operator*=(value_type v)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::multiplies<value_type>{}(x, v); });
return *this;
@@ -227,8 +237,10 @@ public:
constexpr multi_span_index& operator/=(value_type v)
{
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute
// clang-format on
std::transform(elems, elems + rank, elems,
[v](value_type x) { return std::divides<value_type>{}(x, v); });
return *this;
@@ -291,7 +303,9 @@ const std::ptrdiff_t dynamic_range = -1;
struct [[deprecated]] generalized_mapping_tag
{
};
struct[[deprecated]] contiguous_mapping_tag : generalized_mapping_tag{};
struct [[deprecated]] contiguous_mapping_tag : generalized_mapping_tag
{
};
namespace details
{
@@ -303,7 +317,8 @@ namespace details
};
template <std::ptrdiff_t... Ranges>
struct [[deprecated]] BoundsRanges {
struct [[deprecated]] BoundsRanges
{
using size_type = std::ptrdiff_t;
static const size_type Depth = 0;
static const size_type DynamicNum = 0;
@@ -342,7 +357,7 @@ namespace details
};
template <std::ptrdiff_t... RestRanges>
struct[[deprecated]] BoundsRanges<dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>
struct [[deprecated]] BoundsRanges<dynamic_range, RestRanges...> : BoundsRanges<RestRanges...>
{
using Base = BoundsRanges<RestRanges...>;
using size_type = std::ptrdiff_t;
@@ -355,9 +370,10 @@ namespace details
size_type m_bound;
public:
GSL_SUPPRESS(
f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format off
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute // this pointer type is cannot be assigned nullptr - issue in not_null
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr BoundsRanges(const std::ptrdiff_t* const arr)
: Base(arr + 1), m_bound(*arr * this->Base::totalSize())
{
@@ -374,14 +390,16 @@ namespace details
{}
template <typename T, std::size_t Dim = 0>
constexpr void serialize(T & arr) const
constexpr void serialize(T& arr) const
{
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
}
template <typename T, std::size_t Dim = 0>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type linearize(const T& arr) const
{
const size_type index = this->Base::totalSize() * arr[Dim];
@@ -398,19 +416,22 @@ namespace details
return cur < m_bound ? cur + last : -1;
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type totalSize() const noexcept { return m_bound; }
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum() const noexcept
{
return totalSize() / this->Base::totalSize();
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
@@ -427,7 +448,7 @@ namespace details
};
template <std::ptrdiff_t CurRange, std::ptrdiff_t... RestRanges>
struct[[deprecated]] BoundsRanges<CurRange, RestRanges...> : BoundsRanges<RestRanges...>
struct [[deprecated]] BoundsRanges<CurRange, RestRanges...> : BoundsRanges<RestRanges...>
{
using Base = BoundsRanges<RestRanges...>;
using size_type = std::ptrdiff_t;
@@ -445,12 +466,14 @@ namespace details
bool firstLevel = true)
: Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
{
// clang-format off
GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
(void) firstLevel;
}
template <typename T, std::size_t Dim = 0>
constexpr void serialize(T & arr) const
constexpr void serialize(T& arr) const
{
arr[Dim] = elementNum();
this->Base::template serialize<T, Dim + 1>(arr);
@@ -459,9 +482,13 @@ namespace details
template <typename T, std::size_t Dim = 0>
constexpr size_type linearize(const T& arr) const
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(arr[Dim] >= 0 && arr[Dim] < CurrentRange); // Index is out of range
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
const std::ptrdiff_t d = arr[Dim];
return this->Base::totalSize() * d + this->Base::template linearize<T, Dim + 1>(arr);
}
@@ -475,19 +502,22 @@ namespace details
return this->Base::totalSize() * arr[Dim] + last;
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type totalSize() const noexcept
{
return CurrentRange * this->Base::totalSize();
}
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum() const noexcept { return CurrentRange; }
GSL_SUPPRESS(
c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format off
GSL_SUPPRESS(c.128) // NO-FORMAT: attribute // no pointers to BoundsRanges should be ever used
// clang-format on
constexpr size_type elementNum(std::size_t dim) const noexcept
{
if (dim > 0)
@@ -503,14 +533,17 @@ namespace details
};
template <typename SourceType, typename TargetType>
struct[[deprecated]] BoundsRangeConvertible
struct [[deprecated]] BoundsRangeConvertible
: public std::integral_constant<bool, (SourceType::TotalSize >= TargetType::TotalSize ||
TargetType::TotalSize == dynamic_range ||
SourceType::TotalSize == dynamic_range ||
TargetType::TotalSize == 0)>{};
TargetType::TotalSize == 0)>
{
};
template <typename TypeChain>
struct [[deprecated]] TypeListIndexer {
struct [[deprecated]] TypeListIndexer
{
const TypeChain& obj_;
constexpr TypeListIndexer(const TypeChain& obj) : obj_(obj) {}
@@ -523,13 +556,13 @@ namespace details
template <std::size_t N, typename MyChain = TypeChain,
typename MyBase = typename MyChain::Base>
constexpr auto getObj(std::false_type)
->decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
-> decltype(TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>())
{
return TypeListIndexer<MyBase>(static_cast<const MyBase&>(obj_)).template get<N>();
}
template <std::size_t N>
constexpr auto get()->decltype(getObj<N - 1>(std::integral_constant<bool, N == 0>()))
constexpr auto get() -> decltype(getObj<N - 1>(std::integral_constant<bool, N == 0>()))
{
return getObj<N - 1>(std::integral_constant<bool, N == 0>());
}
@@ -548,7 +581,9 @@ namespace details
Ret ret{};
for (std::size_t i = 0; i < Rank - 1; ++i)
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
ret[i] = other[i + 1];
}
return ret;
@@ -559,13 +594,14 @@ template <typename IndexType>
class [[deprecated]] bounds_iterator;
template <std::ptrdiff_t... Ranges>
class [[deprecated]] static_bounds {
class [[deprecated]] static_bounds
{
public:
static_bounds(const details::BoundsRanges<Ranges...>&) {}
};
template <std::ptrdiff_t FirstRange, std::ptrdiff_t... RestRanges>
class[[deprecated]] static_bounds<FirstRange, RestRanges...>
class [[deprecated]] static_bounds<FirstRange, RestRanges...>
{
using MyRanges = details::BoundsRanges<FirstRange, RestRanges...>;
@@ -597,10 +633,10 @@ public:
template <std::size_t Rank, typename SourceType, typename TargetType,
typename Ret = BoundsRangeConvertible2<typename SourceType::Base,
typename TargetType::Base, Rank>>
static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type)->Ret;
static auto helpBoundsRangeConvertible(SourceType, TargetType, std::true_type) -> Ret;
template <std::size_t Rank, typename SourceType, typename TargetType>
static auto helpBoundsRangeConvertible(SourceType, TargetType, ...)->std::false_type;
static auto helpBoundsRangeConvertible(SourceType, TargetType, ...) -> std::false_type;
template <typename SourceType, typename TargetType, std::size_t Rank>
struct BoundsRangeConvertible2
@@ -726,7 +762,8 @@ public:
};
template <std::size_t Rank>
class [[deprecated]] strided_bounds {
class [[deprecated]] strided_bounds
{
template <std::size_t OtherRank>
friend class strided_bounds;
@@ -750,7 +787,7 @@ public:
constexpr strided_bounds& operator=(const strided_bounds&) noexcept = default;
constexpr strided_bounds(const value_type(&values)[rank], index_type strides)
constexpr strided_bounds(const value_type (&values)[rank], index_type strides)
: m_extents(values), m_strides(std::move(strides))
{}
@@ -760,7 +797,9 @@ public:
constexpr index_type strides() const noexcept { return m_strides; }
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type total_size() const noexcept
{
size_type ret = 0;
@@ -768,7 +807,9 @@ public:
return ret + 1;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type size() const noexcept
{
size_type ret = 1;
@@ -785,7 +826,9 @@ public:
return true;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type linearize(const index_type& idx) const
{
size_type ret = 0;
@@ -797,7 +840,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type stride() const noexcept { return m_strides[0]; }
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
@@ -808,7 +853,9 @@ public:
template <std::size_t Dim = 0>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr size_type extent() const noexcept
{
static_assert(Dim < Rank,
@@ -828,14 +875,21 @@ private:
};
template <typename T>
struct[[deprecated]] is_bounds : std::integral_constant<bool, false>{};
struct [[deprecated]] is_bounds : std::integral_constant<bool, false>
{
};
template <std::ptrdiff_t... Ranges>
struct[[deprecated]] is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true>{};
struct [[deprecated]] is_bounds<static_bounds<Ranges...>> : std::integral_constant<bool, true>
{
};
template <std::size_t Rank>
struct[[deprecated]] is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>{};
struct [[deprecated]] is_bounds<strided_bounds<Rank>> : std::integral_constant<bool, true>
{
};
template <typename IndexType>
class [[deprecated]] bounds_iterator {
class [[deprecated]] bounds_iterator
{
public:
static const std::size_t rank = IndexType::rank;
using iterator_category = std::random_access_iterator_tag;
@@ -856,8 +910,10 @@ public:
constexpr pointer operator->() const noexcept { return &curr_; }
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator++() noexcept
{
@@ -882,7 +938,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator--()
{
if (!less(curr_, boundary_))
@@ -919,7 +977,9 @@ public:
return ret += n;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr bounds_iterator& operator+=(difference_type n)
{
auto linear_idx = linearize(curr_) + n;
@@ -969,15 +1029,17 @@ public:
constexpr 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:
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
constexpr bool less(index_type & one, index_type & other) const noexcept
// clang-format on
constexpr bool less(index_type& one, index_type& other) const noexcept
{
for (std::size_t i = 0; i < rank; ++i)
{
@@ -986,7 +1048,9 @@ private:
return false;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr index_size_type linearize(const value_type& idx) const noexcept
{
// TODO: Smarter impl.
@@ -1048,8 +1112,10 @@ namespace details
stride[Bounds::rank - 1] = 1;
for (std::size_t i = 1; i < Bounds::rank; ++i)
{
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
stride[Bounds::rank - i - 1] = stride[Bounds::rank - i] * extents[Bounds::rank - i];
}
return {stride};
@@ -1103,10 +1169,12 @@ constexpr dim_t<N> dim(std::ptrdiff_t n) noexcept
template <typename ValueType, std::ptrdiff_t FirstDimension = dynamic_range,
std::ptrdiff_t... RestDimensions>
class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span;
class [[deprecated(
"gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span;
template <typename ValueType, std::size_t Rank>
class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span;
class [[deprecated(
"gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span;
namespace details
{
@@ -1193,8 +1261,8 @@ namespace details
};
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
struct [[deprecated]] is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>>
: std::true_type
struct [[deprecated]] is_multi_span_oracle<
multi_span<ValueType, FirstDimension, RestDimensions...>> : std::true_type
{
};
@@ -1210,7 +1278,9 @@ namespace details
} // namespace details
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
class [[deprecated("gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span {
class [[deprecated(
"gsl::multi_span is deprecated because it is not in the C++ Core Guidelines")]] multi_span
{
// TODO do we still need this?
template <typename ValueType2, std::ptrdiff_t FirstDimension2,
std::ptrdiff_t... RestDimensions2>
@@ -1242,7 +1312,9 @@ private:
public:
// default constructor - same as constructing from nullptr_t
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span() noexcept : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
@@ -1252,7 +1324,9 @@ public:
}
// construct from nullptr - get an empty multi_span
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(std::nullptr_t) noexcept : multi_span(nullptr, bounds_type{})
{
static_assert(bounds_type::dynamic_rank != 0 ||
@@ -1276,7 +1350,9 @@ public:
// construct from a single element
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(reference data) noexcept : multi_span(&data, bounds_type{1})
{
static_assert(bounds_type::dynamic_rank > 0 || bounds_type::static_size == 0 ||
@@ -1289,7 +1365,9 @@ public:
constexpr multi_span(value_type &&) = delete;
// construct from pointer + length
// clang-format off
GSL_SUPPRESS(type.6) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
constexpr multi_span(pointer ptr, size_type size) : multi_span(ptr, bounds_type{size}) {}
// construct from pointer + length - multidimensional
@@ -1526,7 +1604,9 @@ public:
return this->operator[](idx);
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
@@ -1534,7 +1614,9 @@ public:
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr Ret operator[](size_type idx) const
{
Expects(idx >= 0 && idx < bounds_.size()); // index is out of bounds of the array
@@ -1549,7 +1631,9 @@ public:
constexpr iterator end() const noexcept { return iterator{this, false}; }
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
constexpr const_iterator cbegin() const noexcept
{
return const_iterator{reinterpret_cast<const const_span*>(this), true};
@@ -1647,8 +1731,7 @@ constexpr auto as_multi_span(SpanType s, Dimensions2... dims)
// convert a multi_span<T> to a multi_span<const byte>
template <typename U, std::ptrdiff_t... Dimensions>
multi_span<const byte, dynamic_range>
as_bytes(multi_span<U, Dimensions...> s) noexcept
multi_span<const byte, dynamic_range> as_bytes(multi_span<U, Dimensions...> s) noexcept
{
static_assert(std::is_trivial<std::decay_t<U>>::value,
"The value_type of multi_span must be a trivial type.");
@@ -1734,8 +1817,7 @@ constexpr auto as_multi_span(T* arr, std::ptrdiff_t len) ->
}
template <typename T, std::size_t N>
constexpr auto as_multi_span(T (&arr)[N]) ->
typename details::SpanArrayTraits<T, N>::type
constexpr auto as_multi_span(T (&arr)[N]) -> typename details::SpanArrayTraits<T, N>::type
{
return {arr};
}
@@ -1777,7 +1859,9 @@ constexpr auto as_multi_span(Cont&& arr) -> std::enable_if_t<
// from basic_string which doesn't have nonconst .data() member like other contiguous containers
template <typename CharT, typename Traits, typename Allocator>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
-> multi_span<CharT, dynamic_range>
{
@@ -1788,7 +1872,8 @@ constexpr auto as_multi_span(std::basic_string<CharT, Traits, Allocator>& str)
// strided_span is an extension that is not strictly part of the GSL at this time.
// It is kept here while the multidimensional interface is still being defined.
template <typename ValueType, std::size_t Rank>
class [[deprecated("gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span
class [[deprecated(
"gsl::strided_span is deprecated because it is not in the C++ Core Guidelines")]] strided_span
{
public:
using bounds_type = strided_bounds<Rank>;
@@ -1823,13 +1908,15 @@ public:
Expects((bounds_.size() > 0 && ptr != nullptr) || bounds_.size() == 0);
// Bounds cross data boundaries
Expects(this->bounds().total_size() <= size);
// clang-format off
GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: false positive
// clang-format on
(void) size;
}
// from static array of size N
template <size_type N>
constexpr strided_span(value_type (&values)[N], bounds_type bounds)
constexpr strided_span(value_type(&values)[N], bounds_type bounds)
: strided_span(values, N, std::move(bounds))
{}
@@ -1844,7 +1931,7 @@ public:
// convertible
template <typename OtherValueType, typename = std::enable_if_t<std::is_convertible<
OtherValueType (*)[], value_type (*)[]>::value>>
OtherValueType(*)[], value_type(*)[]>::value>>
constexpr strided_span(const strided_span<OtherValueType, Rank>& other)
: data_(other.data_), bounds_(other.bounds_)
{}
@@ -1863,7 +1950,9 @@ public:
const size_type size = this->bounds().total_size() / d;
// clang-format off
GSL_SUPPRESS(type.3) // NO-FORMAT: attribute
// clang-format on
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
size,
bounds_type{resize_extent(this->bounds().index_bounds(), d),
@@ -1877,14 +1966,18 @@ public:
bounds_type{extents, details::make_stride(bounds())}};
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr reference operator[](const index_type& idx) const
{
return data_[bounds_.linearize(idx)];
}
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr Ret operator[](size_type idx) const
{
Expects(idx < bounds_.size()); // index is out of bounds of the array
@@ -1988,7 +2081,9 @@ private:
static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
{
// The last dimension of the array needs to contain a multiple of new type elements
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0));
index_type ret = extent;
@@ -2001,14 +2096,18 @@ private:
static index_type resize_stride(const index_type& strides, std::ptrdiff_t, void* = nullptr)
{
// Only strided arrays with regular strides can be resized
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
Expects(strides[Rank - 1] == 1);
return strides;
}
template <bool Enabled = (Rank > 1), typename = std::enable_if_t<Enabled>>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
{
// Only strided arrays with regular strides can be resized
@@ -2031,7 +2130,8 @@ private:
};
template <class Span>
class [[deprecated]] contiguous_span_iterator {
class [[deprecated]] contiguous_span_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = typename Span::value_type;
@@ -2046,14 +2146,18 @@ private:
pointer data_;
const Span* m_validator;
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
void validateThis() const
{
// iterator is out of range of the array
Expects(data_ >= m_validator->data_ && data_ < m_validator->data_ + m_validator->size());
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator(const Span* container, bool isbegin)
: data_(isbegin ? container->data_ : container->data_ + container->size())
, m_validator(container)
@@ -2071,7 +2175,9 @@ public:
return data_;
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator& operator++() noexcept
{
++data_;
@@ -2084,7 +2190,9 @@ public:
return ret;
}
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
contiguous_span_iterator& operator--() noexcept
{
--data_;
@@ -2137,7 +2245,7 @@ public:
bool operator>(const contiguous_span_iterator& rhs) const { return rhs < *this; }
bool operator>=(const contiguous_span_iterator& rhs) const { return !(rhs > *this); }
void swap(contiguous_span_iterator & rhs) noexcept
void swap(contiguous_span_iterator& rhs) noexcept
{
std::swap(data_, rhs.data_);
std::swap(m_validator, rhs.m_validator);
@@ -2152,7 +2260,8 @@ contiguous_span_iterator<Span> operator+(typename contiguous_span_iterator<Span>
}
template <typename Span>
class [[deprecated]] general_span_iterator {
class [[deprecated]] general_span_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = typename Span::value_type;
@@ -2218,7 +2327,9 @@ public:
return m_itr - rhs.m_itr;
}
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
// clang-format on
value_type operator[](difference_type n) const { return (*m_container)[m_itr[n]]; }
bool operator==(const general_span_iterator& rhs) const
@@ -2235,7 +2346,7 @@ public:
bool operator<=(const general_span_iterator& rhs) const { return !(rhs < *this); }
bool operator>(const general_span_iterator& rhs) const { return rhs < *this; }
bool operator>=(const general_span_iterator& rhs) const { return !(rhs > *this); }
void swap(general_span_iterator & rhs) noexcept
void swap(general_span_iterator& rhs) noexcept
{
std::swap(m_itr, rhs.m_itr);
std::swap(m_container, rhs.m_container);
@@ -2252,11 +2363,6 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910
#pragma warning(pop)
+49
View File
@@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_NARROW_H
#define GSL_NARROW_H
#include <gsl/assert> // for contracts
#include <gsl/util> // for narrow_cast
namespace gsl
{
struct narrowing_error : public std::exception
{
const char* what() const noexcept override { return "narrowing_error"; }
};
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
// clang-format on
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =
(std::is_signed<T>::value != std::is_signed<U>::value);
const T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
return t;
}
} // namespace gsl
#endif // GSL_NARROW_H
+56 -49
View File
@@ -17,19 +17,17 @@
#ifndef GSL_POINTERS_H
#define GSL_POINTERS_H
#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/assert> // for contracts
#include <algorithm> // for forward
#include <iosfwd> // for ptrdiff_t, nullptr_t, ostream, size_t
#include <cstddef> // for ptrdiff_t, nullptr_t, size_t
#include <memory> // for shared_ptr, unique_ptr
#include <system_error> // for hash
#include <type_traits> // for enable_if_t, is_convertible, is_assignable
#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif // defined(_MSC_VER) && _MSC_VER < 1910
#if !defined(GSL_NO_IOSTREAMS)
#include <iosfwd> // for ostream
#endif // !defined(GSL_NO_IOSTREAMS)
namespace gsl
{
@@ -37,13 +35,14 @@ namespace gsl
//
// GSL.owner: ownership pointers
//
using std::unique_ptr;
using std::shared_ptr;
using std::unique_ptr;
//
// owner
//
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some reason
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some
// reason
//
// T must be a pointer type
// - disallow construction from any type other than pointer type
@@ -69,36 +68,35 @@ template <class T>
class not_null
{
public:
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
static_assert(std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value,
"T cannot be compared to nullptr.");
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
{
Expects(ptr_ != nullptr);
Expects(ptr_ != nullptr, Null);
}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr not_null(T u) : ptr_(u)
constexpr not_null(T u) : ptr_(std::move(u))
{
Expects(ptr_ != nullptr);
Expects(ptr_ != nullptr, Null);
}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(const not_null<U>& other) : not_null(other.get())
{
}
{}
not_null(const not_null& other) = default;
not_null& operator=(const not_null& other) = default;
constexpr T get() const
constexpr std::conditional_t<std::is_copy_constructible<T>::value, T, const T&> get() const
{
Ensures(ptr_ != nullptr);
Ensures(ptr_ != nullptr, Null);
return ptr_;
}
constexpr operator T() const { return get(); }
constexpr T operator->() const { return get(); }
constexpr decltype(auto) operator->() const { return get(); }
constexpr decltype(auto) operator*() const { return *get(); }
// prevents compilation when someone attempts to assign a null pointer constant
@@ -119,49 +117,64 @@ private:
};
template <class T>
auto make_not_null(T&& t) {
auto make_not_null(T&& t) noexcept
{
return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
#if !defined(GSL_NO_IOSTREAMS)
template <class T>
std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
{
os << val.get();
return os;
}
#endif // !defined(GSL_NO_IOSTREAMS)
template <class T, class U>
auto operator==(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() == rhs.get())
auto operator==(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() == rhs.get()))
-> decltype(lhs.get() == rhs.get())
{
return lhs.get() == rhs.get();
}
template <class T, class U>
auto operator!=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() != rhs.get())
auto operator!=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() != rhs.get()))
-> decltype(lhs.get() != rhs.get())
{
return lhs.get() != rhs.get();
}
template <class T, class U>
auto operator<(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() < rhs.get())
auto operator<(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() < rhs.get()))
-> decltype(lhs.get() < rhs.get())
{
return lhs.get() < rhs.get();
}
template <class T, class U>
auto operator<=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() <= rhs.get())
auto operator<=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() <= rhs.get()))
-> decltype(lhs.get() <= rhs.get())
{
return lhs.get() <= rhs.get();
}
template <class T, class U>
auto operator>(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() > rhs.get())
auto operator>(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() > rhs.get()))
-> decltype(lhs.get() > rhs.get())
{
return lhs.get() > rhs.get();
}
template <class T, class U>
auto operator>=(const not_null<T>& lhs, const not_null<U>& rhs) -> decltype(lhs.get() >= rhs.get())
auto operator>=(const not_null<T>& lhs,
const not_null<U>& rhs) noexcept(noexcept(lhs.get() >= rhs.get()))
-> decltype(lhs.get() >= rhs.get())
{
return lhs.get() >= rhs.get();
}
@@ -183,7 +196,7 @@ namespace std
template <class T>
struct hash<gsl::not_null<T>>
{
std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value.get()); }
};
} // namespace std
@@ -209,28 +222,23 @@ namespace gsl
// - remove unnecessary asserts
//
template <class T>
class strict_not_null: public not_null<T>
class strict_not_null : public not_null<T>
{
public:
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr explicit strict_not_null(U&& u) :
not_null<T>(std::forward<U>(u))
constexpr explicit strict_not_null(U&& u) : not_null<T>(std::forward<U>(u))
{}
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr explicit strict_not_null(T u) :
not_null<T>(u)
constexpr explicit strict_not_null(T u) : not_null<T>(u)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const not_null<U>& other) :
not_null<T>(other)
constexpr strict_not_null(const not_null<U>& other) : not_null<T>(other)
{}
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr strict_not_null(const strict_not_null<U>& other) :
not_null<T>(other)
constexpr strict_not_null(const strict_not_null<U>& other) : not_null<T>(other)
{}
strict_not_null(strict_not_null&& other) = default;
@@ -267,15 +275,18 @@ template <class T>
strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;
template <class T>
auto make_strict_not_null(T&& t) {
auto make_strict_not_null(T&& t) noexcept
{
return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
}
#if ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
// deduction guides to prevent the ctad-maybe-unsupported warning
template <class T> not_null(T) -> not_null<T>;
template <class T> strict_not_null(T) -> strict_not_null<T>;
template <class T>
not_null(T) -> not_null<T>;
template <class T>
strict_not_null(T) -> strict_not_null<T>;
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
@@ -286,16 +297,12 @@ namespace std
template <class T>
struct hash<gsl::strict_not_null<T>>
{
std::size_t operator()(const gsl::strict_not_null<T>& value) const { return hash<T>{}(value); }
std::size_t operator()(const gsl::strict_not_null<T>& value) const
{
return hash<T>{}(value.get());
}
};
} // namespace std
#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#undef constexpr
#pragma pop_macro("constexpr")
#endif // defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
#endif // GSL_POINTERS_H
+168 -106
View File
@@ -17,8 +17,9 @@
#ifndef GSL_SPAN_H
#define GSL_SPAN_H
#include <gsl/gsl_assert> // for Expects
#include <gsl/gsl_byte> // for byte
#include <gsl/assert> // for contracts
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
@@ -28,7 +29,7 @@
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
// turn off some warnings that are noisy about our Expects statements
// turn off some warnings that are noisy about our contract checks
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning( \
disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
@@ -38,12 +39,6 @@
#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
#endif // _MSC_VER < 1910
#endif // _MSC_VER
// See if we have enough C++17 power to use a static constexpr data member
@@ -66,7 +61,7 @@ namespace gsl
{
// [views.constants], constants
constexpr const std::size_t dynamic_extent = static_cast<std::size_t>(-1);
constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
template <class ElementType, std::size_t Extent = dynamic_extent>
class span;
@@ -106,7 +101,7 @@ namespace details
template <std::size_t From, std::size_t To>
struct is_allowed_extent_conversion
: std::integral_constant<bool, From == To || To == gsl::dynamic_extent>
: std::integral_constant<bool, From == To || To == dynamic_extent>
{
};
@@ -142,21 +137,24 @@ namespace details
constexpr reference operator*() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(begin_ && end_, Bounds);
Expects(begin_ <= current_ && current_ < end_, Bounds);
return *current_;
}
constexpr pointer operator->() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(begin_ && end_, Bounds);
Expects(begin_ <= current_ && current_ < end_, Bounds);
return current_;
}
constexpr span_iterator& operator++() noexcept
{
Expects(begin_ && current_ && end_);
Expects(current_ < end_);
Expects(begin_ && current_ && end_, Bounds);
Expects(current_ < end_, Bounds);
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
++current_;
return *this;
}
@@ -170,8 +168,8 @@ namespace details
constexpr span_iterator& operator--() noexcept
{
Expects(begin_ && end_);
Expects(begin_ < current_);
Expects(begin_ && end_, Bounds);
Expects(begin_ < current_, Bounds);
--current_;
return *this;
}
@@ -185,9 +183,12 @@ namespace details
constexpr span_iterator& operator+=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(end_ - current_ >= n);
if (n < 0) Expects(current_ - begin_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(end_ - current_ >= n, Bounds);
if (n < 0) Expects(current_ - begin_ >= -n, Bounds);
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
current_ += n;
return *this;
}
@@ -207,9 +208,9 @@ namespace details
constexpr span_iterator& operator-=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(current_ - begin_ >= n);
if (n < 0) Expects(end_ - current_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(current_ - begin_ >= n, Bounds);
if (n < 0) Expects(end_ - current_ >= -n, Bounds);
current_ -= n;
return *this;
}
@@ -226,7 +227,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr difference_type operator-(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ - rhs.current_;
}
@@ -240,7 +241,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ == rhs.current_;
}
@@ -257,7 +258,7 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr bool operator<(const span_iterator<Type2>& rhs) const noexcept
{
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
Expects(begin_ == rhs.begin_ && end_ == rhs.end_, Bounds);
return current_ < rhs.current_;
}
@@ -293,14 +294,14 @@ namespace details
{ // test that [lhs, rhs) forms a valid range inside an STL algorithm
Expects(lhs.begin_ == rhs.begin_ // range spans have to match
&& lhs.end_ == rhs.end_ &&
lhs.current_ <= rhs.current_); // range must not be transposed
lhs.current_ <= rhs.current_, Bounds); // range must not be transposed
}
constexpr void _Verify_offset(const difference_type n) const noexcept
{ // test that *this + n is within the range of this call
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(end_ - current_ >= n);
if (n < 0) Expects(current_ - begin_ >= -n);
if (n != 0) Expects(begin_ && current_ && end_, Bounds);
if (n > 0) Expects(end_ - current_ >= n, Bounds);
if (n < 0) Expects(current_ - begin_ >= -n, Bounds);
}
// clang-format off
@@ -343,17 +344,18 @@ namespace details
constexpr extent_type() noexcept = default;
template <size_type Other>
constexpr extent_type(extent_type<Other> ext)
{
static_assert(Other == Ext,
"Mismatch between fixed-size extent and size of initializing data.");
Expects(ext.size() == Ext);
}
constexpr explicit extent_type(extent_type<dynamic_extent>);
constexpr extent_type(size_type size) { Expects(size == Ext); }
constexpr explicit extent_type(size_type size) { Expects(size == Ext, Bounds); }
constexpr size_type size() const noexcept { return Ext; }
private:
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
static constexpr const size_type size_ = Ext; // static size equal to Ext
#else
static constexpr size_type size_ = Ext; // static size equal to Ext
#endif
};
template <>
@@ -363,12 +365,12 @@ namespace details
using size_type = std::size_t;
template <size_type Other>
explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
constexpr explicit extent_type(extent_type<Other> ext) : size_(ext.size())
{}
explicit constexpr extent_type(size_type size) : size_(size)
constexpr explicit extent_type(size_type size) : size_(size)
{
Expects(size != dynamic_extent);
Expects(size != dynamic_extent, Bounds);
}
constexpr size_type size() const noexcept { return size_; }
@@ -377,6 +379,12 @@ namespace details
size_type size_;
};
template <std::size_t Ext>
constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext)
{
Expects(ext.size() == Ext, Bounds);
}
template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
struct calculate_subspan_type
{
@@ -420,22 +428,32 @@ public:
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
{}
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
{
if (Extent != dynamic_extent) Expects(count == Extent);
Expects(count == Extent, Bounds);
}
constexpr span(pointer firstElem, pointer lastElem) noexcept
: storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
{}
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
: storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
{
if (Extent != dynamic_extent)
{ Expects(lastElem - firstElem == static_cast<difference_type>(Extent)); }
Expects(lastElem - firstElem == static_cast<difference_type>(Extent), Bounds);
}
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
constexpr span(pointer firstElem, pointer lastElem) noexcept
: storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
{}
template <std::size_t N,
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
constexpr span(element_type (&arr)[N]) noexcept
: storage_(KnownNotNull{arr + 0}, details::extent_type<N>())
: storage_(KnownNotNull{arr}, details::extent_type<N>())
{}
template <
@@ -456,40 +474,78 @@ public:
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
{}
// NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement
// on Container to be a contiguous sequence container.
template <class Container,
class = std::enable_if_t<
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value>>
// NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the
// requirement on Container to be a contiguous sequence container.
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent != dynamic_extent && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent == dynamic_extent && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <class Container,
class = std::enable_if_t<
std::is_const<element_type>::value && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<std::remove_pointer_t<
decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value>>
template <
std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent != dynamic_extent && std::is_const<element_type>::value &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <
std::size_t MyExtent = Extent, class Container,
std::enable_if_t<
MyExtent == dynamic_extent && std::is_const<element_type>::value &&
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value,
int> = 0>
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
{}
constexpr span(const span& other) noexcept = default;
template <
class OtherElementType, std::size_t OtherExtent,
class = std::enable_if_t<
details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<(MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
details::is_allowed_element_type_conversion<OtherElementType,
element_type>::value,
int> = 0>
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
{}
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
std::enable_if_t<MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
details::is_allowed_element_type_conversion<OtherElementType,
element_type>::value,
int> = 0>
constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
{}
~span() noexcept = default;
constexpr span& operator=(const span& other) noexcept = default;
@@ -497,8 +553,8 @@ public:
template <std::size_t Count>
constexpr span<element_type, Count> first() const noexcept
{
Expects(Count <= size());
return {data(), Count};
Expects(Count <= size(), Bounds);
return span<element_type, Count>{data(), Count};
}
template <std::size_t Count>
@@ -507,8 +563,8 @@ public:
// clang-format on
constexpr span<element_type, Count> last() const noexcept
{
Expects(Count <= size());
return {data() + (size() - Count), Count};
Expects(Count <= size(), Bounds);
return span<element_type, Count>{data() + (size() - Count), Count};
}
template <std::size_t Offset, std::size_t Count = dynamic_extent>
@@ -518,26 +574,26 @@ public:
constexpr auto subspan() const noexcept ->
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
{
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)), Bounds);
using type =
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
}
constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
{
Expects(count <= size());
Expects(count <= size(), Bounds);
return {data(), count};
}
constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
{
Expects(count <= size());
Expects(count <= size(), Bounds);
return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
}
constexpr span<element_type, dynamic_extent> subspan(size_type offset,
size_type count = dynamic_extent) const
noexcept
constexpr span<element_type, dynamic_extent>
subspan(size_type offset, size_type count = dynamic_extent) const noexcept
{
return make_subspan(offset, count, subspan_selector<Extent>{});
}
@@ -547,7 +603,7 @@ public:
constexpr size_type size_bytes() const noexcept
{
Expects(size() < dynamic_extent / sizeof(element_type));
Expects(size() < dynamic_extent / sizeof(element_type), Bounds);
return size() * sizeof(element_type);
}
@@ -559,19 +615,19 @@ public:
// clang-format on
constexpr reference operator[](size_type idx) const noexcept
{
Expects(idx < size());
Expects(idx < size(), Bounds);
return data()[idx];
}
constexpr reference front() const noexcept
{
Expects(size() > 0);
Expects(size() > 0, Bounds);
return data()[0];
}
constexpr reference back() const noexcept
{
Expects(size() > 0);
Expects(size() > 0, Bounds);
return data()[size() - 1];
}
@@ -632,14 +688,14 @@ private:
constexpr storage_type(KnownNotNull data, OtherExtentType ext)
: ExtentType(ext), data_(data.p)
{
Expects(ExtentType::size() != dynamic_extent);
Expects(ExtentType::size() != dynamic_extent, Bounds);
}
template <class OtherExtentType>
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
{
Expects(ExtentType::size() != dynamic_extent);
Expects(data || ExtentType::size() == 0);
Expects(ExtentType::size() != dynamic_extent, Bounds);
Expects(data || ExtentType::size() == 0, Bounds);
}
constexpr pointer data() const noexcept { return data_; }
@@ -660,9 +716,8 @@ private:
};
template <std::size_t CallerExtent>
constexpr span<element_type, dynamic_extent> make_subspan(size_type offset, size_type count,
subspan_selector<CallerExtent>) const
noexcept
constexpr span<element_type, dynamic_extent>
make_subspan(size_type offset, size_type count, subspan_selector<CallerExtent>) const noexcept
{
const span<element_type, dynamic_extent> tmp(*this);
return tmp.subspan(offset, count);
@@ -674,11 +729,11 @@ private:
constexpr span<element_type, dynamic_extent>
make_subspan(size_type offset, size_type count, subspan_selector<dynamic_extent>) const noexcept
{
Expects(size() >= offset);
Expects(size() >= offset, Bounds);
if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
Expects(size() - offset >= count);
Expects(size() - offset >= count, Bounds);
return {KnownNotNull{data() + offset}, count};
}
};
@@ -687,13 +742,21 @@ private:
// Deduction Guides
template <class Type, std::size_t Extent>
span(Type (&)[Extent])->span<Type, Extent>;
span(Type (&)[Extent]) -> span<Type, Extent>;
template <class Type, std::size_t Size>
span(std::array<Type, Size>&)->span<Type, Size>;
span(std::array<Type, Size>&) -> span<Type, Size>;
template <class Type, std::size_t Size>
span(const std::array<Type, Size>&)->span<const Type, Size>;
span(const std::array<Type, Size>&) -> span<const Type, Size>;
template <class Container,
class Element = std::remove_pointer_t<decltype(std::declval<Container&>().data())>>
span(Container&) -> span<Element>;
template <class Container,
class Element = std::remove_pointer_t<decltype(std::declval<const Container&>().data())>>
span(const Container&) -> span<Element>;
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
@@ -728,10 +791,12 @@ template <class ElementType, std::size_t Extent>
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(span<ElementType, Extent> s) noexcept
{
using type = span<const byte, details::calculate_byte_size<ElementType, Extent>::value>;
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
return type{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}
template <class ElementType, std::size_t Extent,
@@ -739,20 +804,17 @@ template <class ElementType, std::size_t Extent,
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writable_bytes(span<ElementType, Extent> s) noexcept
{
using type = span<byte, details::calculate_byte_size<ElementType, Extent>::value>;
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
return type{reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910
#pragma warning(pop)
#endif // _MSC_VER
+3 -4
View File
@@ -27,9 +27,8 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gsl/gsl_util> // for narrow_cast, narrow
#include <gsl/span> // for span
#include <gsl/span> // for span
#include <gsl/util> // for narrow_cast, narrow
#include <algorithm> // for lexicographical_compare
#include <cstddef> // for ptrdiff_t, size_t
@@ -125,7 +124,7 @@ template <class ElementType, std::size_t Extent>
constexpr ElementType& at(span<ElementType, Extent> s, index i)
{
// No bounds checking here because it is done in span::operator[] called below
Ensures(i >= 0);
Ensures(i >= 0, Bounds);
return s[narrow_cast<std::size_t>(i)];
}
+149 -98
View File
@@ -17,16 +17,16 @@
#ifndef GSL_STRING_SPAN_H
#define GSL_STRING_SPAN_H
#include <gsl/gsl_assert> // for Ensures, Expects
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
#include <gsl/assert> // for contracts
#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
#include <gsl/util> // for narrow_cast
#include <algorithm> // for equal, lexicographical_compare
#include <array> // for array
#include <cstddef> // for size_t, nullptr_t
#include <cstdint> // for PTRDIFF_MAX
#include <cstring>
#include <string> // for basic_string, allocator, char_traits
#include <string> // for basic_string, allocator, char_traits
#include <type_traits> // for declval, is_convertible, enable_if_t, add_...
#if defined(_MSC_VER) && !defined(__clang__)
@@ -35,13 +35,13 @@
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates
#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes
#pragma warning(disable : 4996) // use of functions & classes marked [[deprecated]]
#endif // _MSC_VER
#if _MSC_VER < 1910
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
#endif // _MSC_VER < 1910
#endif // _MSC_VER
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
namespace gsl
{
@@ -86,7 +86,9 @@ using u32zstring = basic_zstring<char32_t, Extent>;
namespace details
{
template <class CharT>
std::size_t string_length(const CharT* str, std::size_t n)
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
"isocpp/CppCoreGuidelines PR#1680")]] constexpr std::size_t
string_length(const CharT* str, std::size_t n)
{
if (str == nullptr || n == dynamic_extent) return 0;
@@ -108,73 +110,86 @@ namespace details
// Will fail-fast if sentinel cannot be found before max elements are examined.
//
template <typename T, const T Sentinel>
span<T, dynamic_extent> ensure_sentinel(T* seq,
std::size_t max = static_cast<std::size_t>(-1))
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<T, dynamic_extent>
ensure_sentinel(T* seq, std::size_t max = static_cast<std::size_t>(-1))
{
Ensures(seq != nullptr);
Ensures(seq != nullptr, Null);
GSL_SUPPRESS(
f.23) // NO-FORMAT: attribute // TODO: false positive // TODO: suppress does not work
// clang-format off
GSL_SUPPRESS(f.23) // TODO: false positive // TODO: suppress does not work
// clang-format on
auto cur = seq;
Ensures(cur != nullptr); // workaround for removing the warning
Ensures(cur != nullptr, Null); // workaround for removing the warning
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work
// clang-format off
GSL_SUPPRESS(bounds.1) // TODO: suppress does not work
// clang-format on
while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur;
Ensures(*cur == Sentinel);
Ensures(*cur == Sentinel, Bounds);
return {seq, static_cast<std::size_t>(cur - seq)};
}
//
// ensure_z - creates a span for a zero terminated strings.
// Will fail fast if a null-terminator cannot be found before
// the limit of size_type.
// ensure_z - creates a span for a zero terminated strings. The span will not contain the zero
// termination. Will fail fast if a null-terminator cannot be found before the limit of size_type.
//
template <typename CharT>
span<CharT, dynamic_extent> ensure_z(CharT* const& sz,
std::size_t max = static_cast<std::size_t>(-1))
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<CharT, dynamic_extent>
ensure_z(CharT* const& sz, std::size_t max = static_cast<std::size_t>(-1))
{
return ensure_sentinel<CharT, CharT(0)>(sz, max);
}
template <typename CharT, std::size_t N>
span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N])
constexpr span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N])
{
return ensure_z(&sz[0], N);
}
template <class Cont>
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent>
[[deprecated(
"string_span was removed from the C++ Core Guidelines. For more information, see "
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<typename std::
remove_pointer<
typename Cont::pointer>::type,
dynamic_extent>
ensure_z(Cont& cont)
{
return ensure_z(cont.data(), cont.size());
}
template <typename CharT, std::size_t>
class basic_string_span;
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span;
namespace details
{
template <typename T>
struct is_basic_string_span_oracle : std::false_type
{
};
struct [[deprecated(
"string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{};
template <typename CharT, std::size_t Extent>
struct is_basic_string_span_oracle<basic_string_span<CharT, Extent>> : std::true_type
{
};
struct [[deprecated(
"string_span was removed from the C++ Core Guidelines. For more information, see "
"isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle<basic_string_span<CharT,
Extent>>
: std::true_type{};
template <typename T>
struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
{
};
struct [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span
: is_basic_string_span_oracle<std::remove_cv_t<T>>{};
} // namespace details
//
// string_span and relatives
//
template <typename CharT, std::size_t Extent = dynamic_extent>
class basic_string_span
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span
{
public:
using element_type = CharT;
@@ -203,11 +218,11 @@ public:
// From static arrays - if 0-terminated, remove 0 from the view
// All other containers allow 0s within the length, so we do not remove them
template <std::size_t N>
constexpr basic_string_span(element_type (&arr)[N]) : span_(remove_z(arr))
constexpr basic_string_span(element_type(&arr)[N]) : span_(remove_z(arr))
{}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
constexpr basic_string_span(std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
constexpr basic_string_span(std::array<ArrayElementType, N> & arr) noexcept : span_(arr)
{}
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
@@ -216,8 +231,8 @@ public:
// Container signature should work for basic_string after C++17 version exists
template <class Traits, class Allocator>
// GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator>& str)
// GSL_SUPPRESS(bounds.4) // TODO: parser bug
constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator> & str)
: span_(&str[0], str.length())
{}
@@ -233,7 +248,7 @@ public:
std::is_convertible<typename Container::pointer, pointer>::value &&
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr basic_string_span(Container& cont) : span_(cont)
constexpr basic_string_span(Container & cont) : span_(cont)
{}
template <class Container,
@@ -282,8 +297,8 @@ public:
return {span_.template subspan<Offset, Count>()};
}
constexpr basic_string_span<element_type, dynamic_extent>
subspan(size_type offset, size_type count = dynamic_extent) const
constexpr basic_string_span<element_type, dynamic_extent> subspan(
size_type offset, size_type count = dynamic_extent) const
{
return {span_.subspan(offset, count)};
}
@@ -306,13 +321,13 @@ public:
constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
private:
static impl_type remove_z(pointer const& sz, std::size_t max)
static constexpr impl_type remove_z(pointer const& sz, std::size_t max)
{
return {sz, details::string_length(sz, max)};
return impl_type(sz, details::string_length(sz, max));
}
template <std::size_t N>
static impl_type remove_z(element_type (&sz)[N])
static constexpr impl_type remove_z(element_type(&sz)[N])
{
return remove_z(&sz[0], N);
}
@@ -321,35 +336,51 @@ private:
};
template <std::size_t Extent = dynamic_extent>
using string_span = basic_string_span<char, Extent>;
using string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<char, Extent>;
template <std::size_t Extent = dynamic_extent>
using cstring_span = basic_string_span<const char, Extent>;
using cstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<const char, Extent>;
template <std::size_t Extent = dynamic_extent>
using wstring_span = basic_string_span<wchar_t, Extent>;
using wstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<wchar_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using cwstring_span = basic_string_span<const wchar_t, Extent>;
using cwstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<const wchar_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using u16string_span = basic_string_span<char16_t, Extent>;
using u16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<char16_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using cu16string_span = basic_string_span<const char16_t, Extent>;
using cu16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<const char16_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using u32string_span = basic_string_span<char32_t, Extent>;
using u32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<char32_t, Extent>;
template <std::size_t Extent = dynamic_extent>
using cu32string_span = basic_string_span<const char32_t, Extent>;
using cu32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_string_span<const char32_t, Extent>;
//
// to_string() allow (explicit) conversions from string_span to string
//
template <typename CharT, std::size_t Extent>
std::basic_string<typename std::remove_const<CharT>::type>
constexpr std::basic_string<typename std::remove_const<CharT>::type>
to_string(basic_string_span<CharT, Extent> view)
{
return {view.data(), narrow_cast<std::size_t>(view.length())};
@@ -357,32 +388,38 @@ to_string(basic_string_span<CharT, Extent> view)
template <typename CharT, typename Traits = typename std::char_traits<CharT>,
typename Allocator = std::allocator<CharT>, typename gCharT, std::size_t Extent>
std::basic_string<CharT, Traits, Allocator> to_basic_string(basic_string_span<gCharT, Extent> view)
constexpr std::basic_string<CharT, Traits, Allocator>
to_basic_string(basic_string_span<gCharT, Extent> view)
{
return {view.data(), narrow_cast<std::size_t>(view.length())};
}
template <class ElementType, std::size_t Extent>
basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
constexpr basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
as_bytes(basic_string_span<ElementType, Extent> s) noexcept
{
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format off
GSL_SUPPRESS(type.1)
// clang-format on
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}
template <class ElementType, std::size_t Extent,
class = std::enable_if_t<!std::is_const<ElementType>::value>>
basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
constexpr basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
as_writable_bytes(basic_string_span<ElementType, Extent> s) noexcept
{
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format off
GSL_SUPPRESS(type.1)
// clang-format on
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
// zero-terminated string span, used to convert
// zero-terminated spans to legacy strings
template <typename CharT, std::size_t Extent = dynamic_extent>
class basic_zstring_span
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
"see isocpp/CppCoreGuidelines PR#1680")]] basic_zstring_span
{
public:
using value_type = CharT;
@@ -400,14 +437,15 @@ public:
constexpr basic_zstring_span(impl_type s) : span_(s)
{
// expects a zero-terminated span
Expects(s[s.size() - 1] == '\0');
Expects(s.size() > 0, Bounds);
Expects(s[s.size() - 1] == value_type{}, Bounds);
}
// copy
constexpr basic_zstring_span(const basic_zstring_span& other) = default;
// move
constexpr basic_zstring_span(basic_zstring_span&& other) = default;
constexpr basic_zstring_span(basic_zstring_span && other) = default;
// assign
constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;
@@ -415,12 +453,11 @@ public:
// move assign
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
constexpr bool empty() const noexcept { return span_.size() == 0; }
constexpr bool empty() const noexcept { return false; }
constexpr string_span_type as_string_span() const noexcept
{
const auto sz = span_.size();
return {span_.data(), sz > 1 ? sz - 1 : 0};
return {span_.data(), span_.size() - 1};
}
constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); }
@@ -431,28 +468,44 @@ private:
};
template <std::size_t Max = dynamic_extent>
using zstring_span = basic_zstring_span<char, Max>;
using zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<char, Max>;
template <std::size_t Max = dynamic_extent>
using wzstring_span = basic_zstring_span<wchar_t, Max>;
using wzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<wchar_t, Max>;
template <std::size_t Max = dynamic_extent>
using u16zstring_span = basic_zstring_span<char16_t, Max>;
using u16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<char16_t, Max>;
template <std::size_t Max = dynamic_extent>
using u32zstring_span = basic_zstring_span<char32_t, Max>;
using u32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<char32_t, Max>;
template <std::size_t Max = dynamic_extent>
using czstring_span = basic_zstring_span<const char, Max>;
using czstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<const char, Max>;
template <std::size_t Max = dynamic_extent>
using cwzstring_span = basic_zstring_span<const wchar_t, Max>;
using cwzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<const wchar_t, Max>;
template <std::size_t Max = dynamic_extent>
using cu16zstring_span = basic_zstring_span<const char16_t, Max>;
using cu16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For "
"more information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<const char16_t, Max>;
template <std::size_t Max = dynamic_extent>
using cu32zstring_span = basic_zstring_span<const char32_t, Max>;
using cu32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For "
"more information, see isocpp/CppCoreGuidelines PR#1680")]] =
basic_zstring_span<const char32_t, Max>;
// operator ==
template <class CharT, std::size_t Extent, class T,
@@ -476,7 +529,7 @@ bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other
}
// operator !=
template <typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
@@ -485,7 +538,7 @@ bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
@@ -495,7 +548,7 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other)
}
// operator<
template <typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
@@ -505,7 +558,7 @@ bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
@@ -521,7 +574,7 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
// so the cases below are already covered by the previous operators
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -535,7 +588,7 @@ bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -550,7 +603,7 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
#endif
// operator <=
template <typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
@@ -559,7 +612,7 @@ bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
@@ -574,7 +627,7 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
// so the cases below are already covered by the previous operators
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -587,7 +640,7 @@ bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -601,7 +654,7 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
#endif
// operator>
template <typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
@@ -610,7 +663,7 @@ bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
@@ -625,7 +678,7 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
// so the cases below are already covered by the previous operators
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -638,7 +691,7 @@ bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -652,7 +705,7 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
#endif
// operator >=
template <typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<std::is_convertible<
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
@@ -661,7 +714,7 @@ bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
!gsl::details::is_basic_string_span<T>::value>>
@@ -676,7 +729,7 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
// so the cases below are already covered by the previous operators
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -689,7 +742,7 @@ bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
}
template <
typename CharT, std::size_t Extent = gsl::dynamic_extent, typename T,
typename CharT, std::size_t Extent = dynamic_extent, typename T,
typename DataType = typename T::value_type,
typename = std::enable_if_t<
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
@@ -706,11 +759,9 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#if _MSC_VER < 1910
#undef constexpr
#pragma pop_macro("constexpr")
#endif // _MSC_VER < 1910
#endif // _MSC_VER
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif // GSL_STRING_SPAN_H
+145
View File
@@ -0,0 +1,145 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GSL_UTIL_H
#define GSL_UTIL_H
#include <gsl/assert> // for contracts
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
#include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif // _MSC_VER
#if defined(__cplusplus) && (__cplusplus >= 201703L)
#define GSL_NODISCARD [[nodiscard]]
#else
#define GSL_NODISCARD
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)
namespace gsl
{
//
// GSL.util: utilities
//
// index type for all container indexes/subscripts/sizes
using index = std::ptrdiff_t;
// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
!std::is_volatile<F>::value,
"Final_action should store its callable by value");
explicit final_action(F f) noexcept : f_(std::move(f)) {}
final_action(final_action&& other) noexcept
: f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
{}
final_action(const final_action&) = delete;
final_action& operator=(const final_action&) = delete;
final_action& operator=(final_action&&) = delete;
// clang-format off
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
// clang-format on
~final_action() noexcept
{
if (invoke_) f_();
}
private:
F f_;
bool invoke_{true};
};
// finally() - convenience function to generate a final_action
template <class F>
GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>
finally(F&& f) noexcept
{
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
//
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
//
template <class T, std::size_t N>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N), Bounds);
return arr[narrow_cast<std::size_t>(i)];
}
template <class Cont>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()), Bounds);
using size_type = decltype(cont.size());
return cont[narrow_cast<size_type>(i)];
}
template <class T>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()), Bounds);
return *(cont.begin() + i);
}
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif // _MSC_VER
#endif // GSL_UTIL_H
+26
View File
@@ -0,0 +1,26 @@
parameters:
jobName: ''
imageName: ''
jobs:
- job:
displayName: ${{ parameters.imageName }}
pool:
vmImage: ${{ parameters.imageName }}
strategy:
matrix:
14_debug:
GSL_CXX_STANDARD: '14'
BUILD_TYPE: 'Debug'
14_release:
GSL_CXX_STANDARD: '14'
BUILD_TYPE: 'Release'
17_debug:
GSL_CXX_STANDARD: '17'
BUILD_TYPE: 'Debug'
17_release:
GSL_CXX_STANDARD: '17'
BUILD_TYPE: 'Release'
continueOnError: false
steps:
- template: ./steps.yml
+17
View File
@@ -0,0 +1,17 @@
steps:
- task: CMake@1
name: Configure
inputs:
workingDirectory: build
cmakeArgs: '-DCMAKE_CXX_STANDARD=$(GSL_CXX_STANDARD) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) .. '
- task: CMake@1
name: Build
inputs:
workingDirectory: build
cmakeArgs: '--build . '
- script: ctest . --output-on-failure --no-compress-output
name: CTest
workingDirectory: build
failOnStderr: true
+40 -29
View File
@@ -1,37 +1,42 @@
cmake_minimum_required(VERSION 3.0.2)
project(GSLTests CXX)
include(FindPkgConfig)
# will make visual studio generated project group files
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
pkg_search_module(GTestMain gtest_main)
if (NOT GTestMain_FOUND)
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(GTestMain_LIBRARIES gtest_main)
add_subdirectory(
${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL
)
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(
${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL
)
if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
endif()
@@ -73,6 +78,7 @@ if(MSVC) # MSVC or simulating MSVC
-Wno-shift-sign-overflow # GTest gtest-port.h
-Wno-undef # GTest
-Wno-used-but-marked-unused # GTest EXPECT_DEATH
-Wno-global-constructors
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-member-function
-Wno-unused-variable
@@ -104,6 +110,7 @@ else()
-Wno-unknown-attributes
-Wno-used-but-marked-unused # GTest EXPECT_DEATH
-Wno-weak-vtables
-Wno-global-constructors
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-member-function
-Wno-unused-variable
@@ -125,7 +132,8 @@ else()
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,6>>:
-Wduplicated-cond # duplicated if-else conditions
-Wmisleading-indentation
-Wnull-dereference
-Wno-null-dereference
-Wno-array-bounds
$<$<EQUAL:${GSL_CXX_STANDARD},14>: # no support for [[maybe_unused]]
-Wno-unused-variable
>
@@ -149,7 +157,7 @@ function(add_gsl_test name)
target_link_libraries(${name}
GSL
gsl_tests_config
gtest_main
${GTestMain_LIBRARIES}
)
add_test(
${name}
@@ -207,6 +215,7 @@ if(MSVC) # MSVC or simulating MSVC
-Wno-c++98-compat-pedantic
-Wno-missing-prototypes
-Wno-unknown-attributes
-Wno-global-constructors
>
)
else()
@@ -229,6 +238,7 @@ else()
-Wno-missing-prototypes
-Wno-unknown-attributes
-Wno-weak-vtables
-Wno-global-constructors
>
$<$<CXX_COMPILER_ID:GNU>:
-Wdouble-promotion # float implicit to double
@@ -237,7 +247,8 @@ else()
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,6>>:
-Wduplicated-cond # duplicated if-else conditions
-Wmisleading-indentation
-Wnull-dereference
-Wno-null-dereference
-Wno-array-bounds
>
$<$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,7>>:
-Wduplicated-branches # identical if-else branches
@@ -254,7 +265,7 @@ function(add_gsl_test_noexcept name)
target_link_libraries(${name}
GSL
gsl_tests_config_noexcept
gtest_main
${GTestMain_LIBRARIES}
)
add_test(
${name}
+1 -1
View File
@@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_algorithm> // for copy
#include <gsl/algorithm> // for copy
#include <gsl/span> // for span
#include <array> // for array
#include <cstddef> // for size_t
+3 -3
View File
@@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects
#include <gsl/assert> // for fail_fast (ptr only), contracts
using namespace gsl;
@@ -25,14 +25,14 @@ static constexpr char deathstring[] = "Expected Death";
int f(int i)
{
Expects(i > 0 && i < 10);
Expects(i > 0 && i < 10, Testing);
return i;
}
int g(int i)
{
i++;
Ensures(i > 0 && i < 10);
Ensures(i > 0 && i < 10, Testing);
return i;
}
} // namespace
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for at
#include <gsl/util> // for at
#include <array> // for array
#include <cstddef> // for size_t
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
#include <gsl/byte> // for to_byte, to_integer, byte, operator&, ope...
using namespace std;
using namespace gsl;
+2 -2
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <gsl/multi_span> // for multi_span, contiguous_span_iterator, dim
#include <algorithm> // for fill, for_each
+15
View File
@@ -533,3 +533,18 @@ TEST(notnull_tests, TestMakeNotNull)
}
#endif
}
TEST(notnull_tests, TestStdHash)
{
int x = 42;
int y = 99;
not_null<int*> nn{&x};
const not_null<int*> cnn{&x};
std::hash<not_null<int*>> hash_nn;
std::hash<int*> hash_intptr;
EXPECT_TRUE(hash_nn(nn) == hash_intptr(&x));
EXPECT_FALSE(hash_nn(nn) == hash_intptr(&y));
EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr));
}
+9 -7
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/byte> // for byte
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
@@ -846,8 +846,6 @@ static_assert(!std::is_constructible<gsl::span<int, 3>, std::array<int, 500>&>::
"!std::is_constructible<gsl::span<int, 3>, std::array<int, 500>&>");
static_assert(!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>::value,
"!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>");
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>::value,
"!std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>");
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>::value,
"!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>");
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<const int>&>::value,
@@ -866,12 +864,8 @@ static_assert(!std::is_constructible<gsl::span<const int>, std::array<double, 3>
static_assert(!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>::value,
"!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>");
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>::value,
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>");
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>::value,
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>");
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>::value,
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>");
static_assert(
!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>::value,
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>");
@@ -925,6 +919,14 @@ static_assert(!std::is_constructible<gsl::span<const Derived>, std::array<Base,
static_assert(!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>::value,
"!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>");
// Explicit construction enabled in P1976R2
static_assert(std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>::value,
"std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>");
static_assert(std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>::value,
"std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>");
static_assert(std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>::value,
"std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>");
// no throw copy constructor
static_assert(std::is_nothrow_copy_constructible<gsl::span<int>>::value,
"std::is_nothrow_copy_constructible<gsl::span<int>>");
+1 -1
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for narrow_cast, at
#include <gsl/util> // for narrow_cast, at
#include <gsl/span_ext> // for operator==, operator!=, make_span
#include <array> // for array
+38 -4
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast, at
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast, at
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
@@ -31,6 +31,16 @@
#include <vector> // for vector
#include <utility>
// the string_view include and macro are used in the deduction guide verification
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
#ifdef __has_include
#if __has_include(<string_view>)
#include <string_view>
#define HAS_STRING_VIEW
#endif // __has_include(<string_view>)
#endif // __has_include
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
using namespace std;
using namespace gsl;
@@ -1144,7 +1154,7 @@ TEST(span_test, from_array_constructor)
// you can convert statically
{
const span<int, 2> s2 = {&arr[0], 2};
const span<int, 2> s2{&arr[0], 2};
static_cast<void>(s2);
}
{
@@ -1180,7 +1190,7 @@ TEST(span_test, from_array_constructor)
#endif
{
auto f = [&]() {
const span<int, 4> _s4 = {arr2, 2};
const span<int, 4> _s4{arr2, 2};
static_cast<void>(_s4);
};
EXPECT_DEATH(f(), deathstring);
@@ -1227,6 +1237,30 @@ TEST(span_test, from_array_constructor)
EXPECT_FALSE((std::is_default_constructible<span<int, 42>>::value));
}
TEST(span_test, std_container_ctad)
{
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
// this test is just to verify that these compile
{
std::vector<int> v{1,2,3,4};
gsl::span sp{v};
static_assert(std::is_same<decltype(sp), gsl::span<int>>::value);
}
{
std::string str{"foo"};
gsl::span sp{str};
static_assert(std::is_same<decltype(sp), gsl::span<char>>::value);
}
#ifdef HAS_STRING_VIEW
{
std::string_view sv{"foo"};
gsl::span sp{sv};
static_assert(std::is_same<decltype(sp), gsl::span<const char>>::value);
}
#endif
#endif
}
TEST(span_test, front_back)
{
int arr[5] = {1,2,3,4,5};
+2 -2
View File
@@ -15,8 +15,8 @@
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#include <gsl/multi_span> // for strided_span, index, multi_span, strided_...
#include <iostream> // for size_t
+5 -5
View File
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/gsl_assert> // for Expects, fail_fast (ptr only)
#include <gsl/assert> // for contracts, fail_fast (ptr only)
#include <gsl/pointers> // for owner
#include <gsl/span> // for span, dynamic_extent
#include <gsl/string_span> // for basic_string_span, operator==, ensure_z
@@ -82,7 +82,7 @@ void use(basic_string_span<T, gsl::dynamic_extent>)
czstring_span<> CreateTempName(string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -99,7 +99,7 @@ czstring_span<> CreateTempName(string_span<> span)
cwzstring_span<> CreateTempNameW(wstring_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -116,7 +116,7 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
@@ -133,7 +133,7 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
{
Expects(span.size() > 1);
Expects(span.size() > 1, Testing);
std::size_t last = 0;
if (span.size() > 4) {
+24 -6
View File
@@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e...
#include <gsl/util> // finally, narrow_cast
#include <gsl/narrow> // for narrow, narrowing_error
#include <algorithm> // for move
#include <functional> // for reference_wrapper, _Bind_helper<>::type
#include <limits> // for numeric_limits
@@ -70,6 +70,28 @@ TEST(utils_tests, finally_lambda_move)
EXPECT_TRUE(i == 1);
}
TEST(utils_tests, finally_const_lvalue_lambda)
{
int i = 0;
{
const auto const_lvalue_lambda = [&]() { f(i); };
auto _ = finally(const_lvalue_lambda);
EXPECT_TRUE(i == 0);
}
EXPECT_TRUE(i == 1);
}
TEST(utils_tests, finally_mutable_lvalue_lambda)
{
int i = 0;
{
auto mutable_lvalue_lambda = [&]() { f(i); };
auto _ = finally(mutable_lvalue_lambda);
EXPECT_TRUE(i == 0);
}
EXPECT_TRUE(i == 1);
}
TEST(utils_tests, finally_function_with_bind)
{
int i = 0;
@@ -122,8 +144,4 @@ TEST(utils_tests, narrow)
n = -42;
EXPECT_THROW(narrow<unsigned>(n), narrowing_error);
#if GSL_CONSTEXPR_NARROW
static_assert(narrow<char>(120) == 120, "Fix GSL_CONSTEXPR_NARROW");
#endif
}