Giter VIP home page Giter VIP logo

span-lite's Introduction

span lite: A single-file header-only version of a C++20-like span for C++98, C++11 and later

Language License Build Status Build status Version download Conan Try it on wandbox Try it on godbolt online

Contents

Example usage

#include "nonstd/span.hpp"
#include <array>
#include <vector>
#include <iostream>

std::ptrdiff_t size( nonstd::span<const int> spn )
{
    return spn.size();
}

int main()
{
    int arr[] = { 1, };

    std::cout << 
        "C-array:" << size( arr ) <<
        " array:"  << size( std::array <int, 2>{ 1, 2, } ) <<
        " vector:" << size( std::vector<int   >{ 1, 2, 3, } );
}

Compile and run

prompt> g++ -std=c++11 -Wall -I../include -o 01-basic.exe 01-basic.cpp && 01-basic.exe
C-array:1 array:2 vector:3

In a nutshell

span lite is a single-file header-only library to provide a bounds-safe view for sequences of objects. The library provides a C++20-like span for use with C++98 and later. If available, std::span is used, unless configured otherwise. span-lite can detect the presence of byte-lite and if present, it provides as_bytes() and as_writable_bytes() also for C++14 and earlier.

Features and properties of span lite are ease of installation (single header), freedom of dependencies other than the standard library. To compensate for the class template argument deduction that is missing from pre-C++17 compilers, nonstd::span can provide make_span functions. See configuration.

License

span lite is distributed under the Boost Software License.

Dependencies

span lite has no other dependencies than the C++ standard library.

Installation and use

span lite is a single-file header-only library. Put span.hpp in the include folder directly into the project source tree or somewhere reachable from your project.

Synopsis

Contents
Documentation of std::span
Later additions
Non-standard extensions
Configuration

Documentation of std::span

Depending on the compiler and C++-standard used, nonstd::span behaves less or more like std::span. To get an idea of the capabilities of nonstd::span with your configuration, look at the output of the tests, issuing span-main.t --pass @. For std::span, see its documentation at cppreference.

Later additions

back() and front()

span lite can provide back() and front() member functions for element access. See the table below and section configuration.

Non-standard extensions

Construct from std::initializer_list (p2447)

span lite can provide construction from a std::initializer_list<> as a constant set of values as proposed in p2447. See the table below and section configuration.

Construct from container

To construct a span from a container with compilers that cannot constrain such a single-parameter constructor to containers, span lite provides a constructor that takes an additional parameter of type with_container_t. Use with_container as value for this parameter. See the table below and section configuration.

Construct from std::array with const data

span lite can provide construction of a span from a std::array with const data. See the table below and section configuration.

operator()

span lite can provide member function call operator() for element access. It is equivalent to operator[] and has been marked [[deprecated]]. Its main purpose is to provide a migration path.

at()

span lite can provide member function at() for element access. Unless exceptions have been disabled, at() throws std::out_of_range if the index falls outside the span. With exceptions disabled, at(index_t) delegates bounds checking to operator[](index_t). See the table below and sections configuration and disable exceptions.

swap()

span lite can provide a swap()member function. See the table below and section configuration.

operator==() and other comparison functions

span lite can provide functions to compare the content of two spans. However, C++20's span will not provide comparison and span lite will omit comparison at default in the near future. See the table below and section configuration. See also Revisiting Regular Types.

same()

span lite can provide function same() to determine if two spans refer as identical spans to the same data via the same type. If same() is enabled, operator==() incorporates it in its comparison. See the table below and section configuration.

first(), last() and subspan()

span lite can provide functions first(), last() and subspan() to avoid having to use the dot template syntax when the span is a dependent type. See the table below and section configuration.

make_span()

span lite can provide make_span() creator functions to compensate for the class template argument deduction that is missing from pre-C++17 compilers. See the table below and section configuration.

byte_span()

span lite can provide byte_span() creator functions to represent an object as a span of bytes. This requires the C++17 type std::byte to be available. See the table below and section configuration.

Kind std Function or method
Macro   macro span_FEATURE_WITH_INITIALIZER_LIST_P2447
Constructor
 
  constexpr explicit span( std::initializer_list<value_type> il ) noexcept
explicit for non-dynamic extent
     
Macro
 
  macro span_FEATURE_WITH_CONTAINER
macro span_FEATURE_WITH_CONTAINER_TO_STD
Types   with_container_t type to disambiguate below constructors
Objects   with_container value to disambiguate below constructors
Constructors   macro span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE
    template<class Container>
constexpr span(with_container_t, Container & cont)
    template<class Container>
constexpr span(with_container_t, Container const & cont)
     
Methods   macro span_FEATURE_MEMBER_CALL_OPERATOR
    constexpr reference operator()(index_t idx) const
Equivalent to operator[](), marked [[deprecated]]
     
Methods   macro span_FEATURE_MEMBER_AT
    constexpr reference at(index_t idx) const
May throw std::out_of_range exception
     
Methods   macro span_FEATURE_MEMBER_BACK_FRONT (on since v0.5.0)
    constexpr reference back() const noexcept
    constexpr reference front() const noexcept
     
Method   macro span_FEATURE_MEMBER_SWAP
    constexpr void swap(span & other) noexcept
     
Free functions   macro span_FEATURE_COMPARISON


== != < > <= >=
  template<class T1, index_t E1, class T2, index_t E2>
constexpr bool
operator==( span<T1,E1> const & l, span<T2,E2> const & r) noexcept
     
Free function   macro span_FEATURE_SAME
    template<class T1, index_t E1, class T2, index_t E2>
constexpr bool
same( span<T1,E1> const & l, span<T2,E2> const & r) noexcept
     
Free functions
 
 
  macros span_FEATURE_NON_MEMBER_FIRST_LAST_SUB,
span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN,
span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER
     
Free functions   macro span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN
    template<extent_t Count, class T, extent_t Extent>
constexpr span<T,Count>
first(span<T,Extent> spn)
    template<class T, extent_t Extent >
constexpr span<T>
first(span<T,Extent> spn, size_t count)
    template<extent_t Count, class T, extent_t Extent>
constexpr span<T,Count>
last(span<T,Extent> spn)
    template<class T, extent_t Extent >
constexpr span<T>
last(span<T,Extent> spn, size_t count)
    template<size_t Offset, extent_t Count, class T, extent_t Extent>
constexpr span<T, Count>
subspan(span<T, Extent> spn)
    template<class T, extent_t Extent>
constexpr span<T>
subspan( span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent)
     
Free functions   macro span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER
  >= C++11 template<extent_t Count, class T>
constexpr auto
first(T & t) ->...
  >= C++11 template<class T>
constexpr auto
first(T & t, index_t count) ->...
  >= C++11 template<extent_t Count, class T>
constexpr auto
last(T & t) ->...
  >= C++11 template<class T>
constexpr auto
last(T & t, extent_t count) ->...
  >= C++11 template<index_t Offset, extent_t Count = dynamic_extent, class T>
constexpr auto
subspan(T & t) ->...
  >= C++11 template<class T>
constexpr auto
subspan(T & t, index_t offset, extent_t count = dynamic_extent) ->...
     
Free functions
 
  macro span_FEATURE_MAKE_SPAN
macro span_FEATURE_MAKE_SPAN_TO_STD
    template<class T>
constexpr span<T>
make_span(T * first, T * last) noexcept
    template<class T>
constexpr span<T>
make_span(T * ptr, index_t count) noexcept
    template<class T, size_t N>
constexpr span<T,N>
make_span(T (&arr)[N]) noexcept
  >= C++11 template<class T, size_t N>
constexpr span<T,N>
make_span(std::array<T,N> & arr) noexcept
  >= C++11 template<class T, size_t N>
constexpr span<const T,N>
make_span(std::array<T,N > const & arr) noexcept
  >= C++11 template<class T>
constexpr span<T>
make_span(std::initializer_list<T> il) noexcept
  >= C++11 template<class Container>
constexpr auto
make_span(Container & cont) ->
 span<typename Container::value_type> noexcept
  >= C++11 template<class Container>
constexpr auto
make_span(Container const & cont) ->
 span<const typename Container::value_type> noexcept
    template<class Container>
span<typename Container::value_type>
make_span( with_container_t, Container & cont )
    template<class Container>
span<const typename Container::value_type>
make_span( with_container_t, Container const & cont )
  < C++11 template<class T, Allocator>
span<T>
make_span(std::vector<T, Allocator> & cont)
  < C++11 template<class T, Allocator>
span<const T>
make_span(std::vector<T, Allocator> const & cont)
     
Free functions   macro span_FEATURE_BYTE_SPAN
  >= C++11 template<class T>
span<T, sizeof(T)>
byte_span(T & t)
  >= C++11 template<class T>
span<const T, sizeof(T)>
byte_span(T const & t)

Configuration

Tweak header

If the compiler supports __has_include(), span lite supports the tweak header mechanism. Provide your tweak header as nonstd/span.tweak.hpp in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like #define span_CONFIG_NO_EXCEPTIONS 1.

Standard selection macro

-Dspan_CPLUSPLUS=199711L
Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the __cplusplus macro correctly.

Select std::span or nonstd::span

At default, span lite uses std::span if it is available and lets you use it via namespace nonstd. You can however override this default and explicitly request to use std::span or span lite's nonstd::span as nonstd::span via the following macros.

-Dspan_CONFIG_SELECT_SPAN=span_SPAN_DEFAULT
Define this to span_SPAN_STD to select std::span as nonstd::span. Define this to span_SPAN_NONSTD to select nonstd::span as nonstd::span. Default is undefined, which has the same effect as defining to span_SPAN_DEFAULT.

Select extent type

-Dspan_CONFIG_EXTENT_TYPE=std::size_t
Define this to std::ptrdiff_t to use the signed type. The default is std::size_t, as in C++20 (since v0.7.0).

Select size type

-Dspan_CONFIG_SIZE_TYPE=std::size_t
Define this to std::ptrdiff_t to use the signed type. The default is std::size_t, as in C++20 (since v0.7.0). Note span_CONFIG_SIZE_TYPE replaces span_CONFIG_INDEX_TYPE which is deprecated.

Disable exceptions

-Dspan_CONFIG_NO_EXCEPTIONS=0
Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via -fno-exceptions). Disabling exceptions will force contract violation to use termination, see contract violation macros. Default is undefined.

Provide construction from std::initializer_list (p2447)

-Dspan_FEATURE_WITH_INITIALIZER_LIST_P2447=0
Define this to 1 to enable constructing a span from a std::initializer_list<> as a constant set of values. See proposal p2447. Default is undefined.

Provide construction using with_container_t

-Dspan_FEATURE_WITH_CONTAINER=0
Define this to 1 to enable constructing a span using with_container_t. Note that span_FEATURE_WITH_CONTAINER takes precedence over span_FEATURE_WITH_CONTAINER_TO_STD. Default is undefined.

-Dspan_FEATURE_WITH_CONTAINER_TO_STD=n
Define this to the highest C++ language version for which to enable constructing a span using with_container_t, like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use span_FEATURE_WITH_CONTAINER for this. Note that span_FEATURE_WITH_CONTAINER takes precedence over span_FEATURE_WITH_CONTAINER_TO_STD. Default is undefined.

Provide construction from std::array with const data

-Dspan_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE=0
Define this to 1 to enable constructing a span from a std::array with const data. Default is undefined.

Provide operator() member function

-Dspan_FEATURE_MEMBER_CALL_OPERATOR=0
Define this to 1 to provide member function operator()for element access. It is equivalent to operator[] and has been marked [[deprecated]]. Its main purpose is to provide a migration path. Default is undefined.

Provide at() member function

-Dspan_FEATURE_MEMBER_AT=0
Define this to 1 to provide member function at(). Define this to 2 to include index and size in message of std::out_of_range exception. Default is undefined.

Provide back() and front() member functions

-Dspan_FEATURE_MEMBER_BACK_FRONT=1 (on since v0.5.0)
Define this to 0 to omit member functions back() and front(). Default is undefined.

Provide swap() member function

-Dspan_FEATURE_MEMBER_SWAP=0
Define this to 1 to provide member function swap(). Default is undefined.

Provide operator==() and other comparison functions

-Dspan_FEATURE_COMPARISON=0
Define this to 1 to include the comparison functions to compare the content of two spans. C++20's span does not provide comparison and span lite omits comparison from v0.7.0. Default is undefined.

Provide same() function

-Dspan_FEATURE_SAME=0
Define this to 1 to provide function same() to test if two spans refer as identical spans to the same data via the same type. If same() is enabled, operator==() incorporates it in its comparison. Default is undefined.

Provide first(), last() and subspan() functions

-Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB=0
Define this to 1 to enable both span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN and span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER. Default is undefined.

-Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN=0
Define this to 1 to provide functions first(), last() and subspan() that take a span<> (work with C++98). This implies span_FEATURE_MAKE_SPAN to provide functions make_span() that are required for this feature. Default is undefined.

-Dspan_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER=0
Define this to 1 to provide functions first(), last() and subspan() that take a compatible container (requires C++11). This implies span_FEATURE_MAKE_SPAN to provide functions make_span() that are required for this feature. Default is undefined.

Provide make_span() functions

-Dspan_FEATURE_MAKE_SPAN=0
Define this to 1 to provide creator functions nonstd::make_span(). This feature is implied by using span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1. Note that span_FEATURE_MAKE_SPAN takes precedence over span_FEATURE_MAKE_SPAN_TO_STD. Default is undefined.

-Dspan_FEATURE_MAKE_SPAN_TO_STD=n
Define this to the highest C++ language version for which to provide creator functions nonstd::make_span(), like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use span_FEATURE_MAKE_SPAN for this. Note that span_FEATURE_MAKE_SPAN takes precedence over span_FEATURE_MAKE_SPAN_TO_STD. Default is undefined.

Provide byte_span() functions

-Dspan_FEATURE_BYTE_SPAN=0
Define this to 1 to provide creator functions nonstd::byte_span(). Default is undefined.

Contract violation response macros

span-lite provides contract violation response control as suggested in proposal N4415.

-Dspan_CONFIG_CONTRACT_LEVEL_ON (default)
Define this macro to include both span_EXPECTS and span_ENSURES in the code. This is the default case.

-Dspan_CONFIG_CONTRACT_LEVEL_OFF
Define this macro to exclude both span_EXPECTS and span_ENSURES from the code.

-Dspan_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY
Define this macro to include span_EXPECTS in the code and exclude span_ENSURES from the code.

-Dspan_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY
Define this macro to exclude span_EXPECTS from the code and include span_ENSURES in the code.

-Dspan_CONFIG_CONTRACT_VIOLATION_TERMINATES (default)
Define this macro to call std::terminate() on a contract violation in span_EXPECTS, span_ENSURES. This is the default case.

-Dspan_CONFIG_CONTRACT_VIOLATION_THROWS
Define this macro to throw an exception of implementation-defined type that is derived from std::runtime_exception instead of calling std::terminate() on a contract violation in span_EXPECTS and span_ENSURES. See also disable exceptions.

Reported to work with

The table below mentions the compiler versions span lite is reported to work with.

OS Compiler Where Versions
GNU/Linux Clang/LLVM Travis 3.5.0, 3.6.2, 3.7.1, 3.8.0, 3.9.1, 4.0.1
  GCC Travis 5.5.0, 6.4.0, 7.3.0
OS X ? Local ?
Windows Clang/LLVM Local 6.0.0
  GCC Local 7.2.0
  Visual C++
(Visual Studio)
Local 8 (2005), 10 (2010), 11 (2012),
12 (2013), 14 (2015), 15 (2017)
  Visual C++
(Visual Studio)
AppVeyor 10 (2010), 11 (2012),
12 (2013), 14 (2015), 15 (2017)

Building the tests

To build the tests you need:

The lest test framework is included in the test folder.

The following steps assume that the span lite source code has been cloned into a directory named ./span-lite.

  1. Create a directory for the build outputs.

     cd ./span-lite
     md build && cd build
    
  2. Configure CMake to use the compiler of your choice (run cmake --help for a list).

     cmake -G "Unix Makefiles" -DSPAN_LITE_OPT_BUILD_TESTS=ON ..
    
  3. Optional. You can control above configuration through the following options:

    -DSPAN_LITE_OPT_BUILD_TESTS=ON: build the tests for span, default off
    -DSPAN_LITE_OPT_BUILD_EXAMPLES=OFF: build the examples, default off

  4. Build the test suite.

     cmake --build .
    
  5. Run the test suite.

     ctest -V
    

All tests should pass, indicating your platform is supported and you are ready to use span lite.

Other implementations of span

Notes and references

Interface and specification

Presentations

  • TBD

Proposals

Appendix

A.1 Compile-time information

The version of span lite is available via tag [.version]. The following tags are available for information on the compiler and on the C++ standard library used: [.compiler], [.stdc++], [.stdlanguage] and [.stdlibrary].

A.2 Span lite test specification

click to expand

span<>: Terminates construction from a nullptr and a non-zero size (C++11)
span<>: Terminates construction from two pointers in the wrong order
span<>: Terminates construction from a null pointer and a non-zero size
span<>: Terminates creation of a sub span of the first n elements for n exceeding the span
span<>: Terminates creation of a sub span of the last n elements for n exceeding the span
span<>: Terminates creation of a sub span outside the span
span<>: Terminates access outside the span
span<>: Throws  on access outside the span via at(): std::out_of_range [span_FEATURE_MEMBER_AT>0][span_CONFIG_NO_EXCEPTIONS=0]
span<>: Termination throws std::logic_error-derived exception [span_CONFIG_CONTRACT_VIOLATION_THROWS=1]
span<>: Allows to default-construct
span<>: Allows to construct from a nullptr and a zero size (C++11)
span<>: Allows to construct from two pointers
span<>: Allows to construct from two iterators
span<>: Allows to construct from two iterators - empty range
span<>: Allows to construct from two iterators - move-only element
span<>: Allows to construct from an iterator and a size
span<>: Allows to construct from an iterator and a size - empty range
span<>: Allows to construct from an iterator and a size - move-only element
span<>: Allows to construct from two pointers to const
span<>: Allows to construct from a non-null pointer and a size
span<>: Allows to construct from a non-null pointer to const and a size
span<>: Allows to construct from a temporary pointer and a size
span<>: Allows to construct from a temporary pointer to const and a size
span<>: Allows to construct from any pointer and a zero size (C++98)
span<>: Allows to construct from a pointer and a size via a deduction guide (C++17)
span<>: Allows to construct from an iterator and a size via a deduction guide (C++17)
span<>: Allows to construct from two iterators via a deduction guide (C++17)
span<>: Allows to construct from a C-array
span<>: Allows to construct from a C-array via a deduction guide (C++17)
span<>: Allows to construct from a const C-array
span<>: Allows to construct from a C-array with size via decay to pointer (potentially dangerous)
span<>: Allows to construct from a const C-array with size via decay to pointer (potentially dangerous)
span<>: Allows to construct from a std::initializer_list<> (C++11)
span<>: Allows to construct from a std::initializer_list<> as a constant set of values (C++11, p2447)
span<>: Allows to construct from a std::array<> (C++11)
span<>: Allows to construct from a std::array via a deduction guide (C++17)
span<>: Allows to construct from a std::array<> with const data (C++11, span_FEATURE_CONSTR..._ELEMENT_TYPE=1)
span<>: Allows to construct from an empty std::array<> (C++11)
span<>: Allows to construct from a container (std::vector<>)
span<>: Allows to construct from a container via a deduction guide (std::vector<>, C++17)
span<>: Allows to tag-construct from a container (std::vector<>)
span<>: Allows to tag-construct from a const container (std::vector<>)
span<>: Allows to copy-construct from another span of the same type
span<>: Allows to copy-construct from another span of a compatible type
span<>: Allows to copy-construct from a temporary span of the same type (C++11)
span<>: Allows to copy-assign from another span of the same type
span<>: Allows to copy-assign from a temporary span of the same type (C++11)
span<>: Allows to create a sub span of the first n elements
span<>: Allows to create a sub span of the last n elements
span<>: Allows to create a sub span starting at a given offset
span<>: Allows to create a sub span starting at a given offset with a given length
span<>: Allows to observe an element via array indexing
span<>: Allows to observe an element via call indexing
span<>: Allows to observe an element via at() [span_FEATURE_MEMBER_AT>0]
span<>: Allows to observe an element via data()
span<>: Allows to observe the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1]
span<>: Allows to observe the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1]
span<>: Allows to change an element via array indexing
span<>: Allows to change an element via call indexing
span<>: Allows to change an element via at() [span_FEATURE_MEMBER_AT>0]
span<>: Allows to change an element via data()
span<>: Allows to change the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1]
span<>: Allows to change the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1]
span<>: Allows to swap with another span [span_FEATURE_MEMBER_SWAP=1]
span<>: Allows forward iteration
span<>: Allows const forward iteration
span<>: Allows reverse iteration
span<>: Allows const reverse iteration
span<>: Allows to identify if a span is the same as another span [span_FEATURE_SAME=1]
span<>: Allows to compare equal to another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare unequal to another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare less than another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare less than or equal to another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare greater than another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare greater than or equal to another span of the same type [span_FEATURE_COMPARISON=1]
span<>: Allows to compare to another span of the same type and different cv-ness [span_FEATURE_SAME=0]
span<>: Allows to compare empty spans as equal [span_FEATURE_COMPARISON=1]
span<>: Allows to test for empty span via empty(), empty case
span<>: Allows to test for empty span via empty(), non-empty case
span<>: Allows to obtain the number of elements via size()
span<>: Allows to obtain the number of elements via ssize()
span<>: Allows to obtain the number of bytes via size_bytes()
span<>: Allows to view the elements as read-only bytes
span<>: Allows to view and change the elements as writable bytes
make_span() [span_FEATURE_MAKE_SPAN_TO_STD=99]
make_span(): Allows building from two pointers
make_span(): Allows building from two const pointers
make_span(): Allows building from a non-null pointer and a size
make_span(): Allows building from a non-null const pointer and a size
make_span(): Allows building from a C-array
make_span(): Allows building from a const C-array
make_span(): Allows building from a std::initializer_list<> (C++11)
make_span(): Allows building from a std::initializer_list<> as a constant set of values (C++11)
make_span(): Allows building from a std::array<> (C++11)
make_span(): Allows building from a const std::array<> (C++11)
make_span(): Allows building from a container (std::vector<>)
make_span(): Allows building from a const container (std::vector<>)
make_span(): Allows building from a container (with_container_t, std::vector<>)
make_span(): Allows building from a const container (with_container_t, std::vector<>)
byte_span() [span_FEATURE_BYTE_SPAN=1]
byte_span(): Allows building a span of std::byte from a single object (C++17, byte-lite)
byte_span(): Allows building a span of const std::byte from a single const object (C++17, byte-lite)
first(), last(), subspan() [span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1]
first(): Allows to create a sub span of the first n elements (span, template parameter)
first(): Allows to create a sub span of the first n elements (span, function parameter)
first(): Allows to create a sub span of the first n elements (compatible container, template parameter)
first(): Allows to create a sub span of the first n elements (compatible container, function parameter)
last(): Allows to create a sub span of the last n elements (span, template parameter)
last(): Allows to create a sub span of the last n elements (span, function parameter)
last(): Allows to create a sub span of the last n elements (compatible container, template parameter)
last(): Allows to create a sub span of the last n elements (compatible container, function parameter)
subspan(): Allows to create a sub span starting at a given offset (span, template parameter)
subspan(): Allows to create a sub span starting at a given offset (span, function parameter)
subspan(): Allows to create a sub span starting at a given offset (compatible container, template parameter)
subspan(): Allows to create a sub span starting at a given offset (compatible container, function parameter)
size(): Allows to obtain the number of elements via size()
ssize(): Allows to obtain the number of elements via ssize()
tuple_size<>: Allows to obtain the number of elements via std::tuple_size<> (C++11)
tuple_element<>: Allows to obtain an element via std::tuple_element<> (C++11)
tuple_element<>: Allows to obtain an element via std::tuple_element_t<> (C++11)
get<I>(spn): Allows to access an element via std::get<>()
tweak header: reads tweak header if supported [tweak]

span-lite's People

Contributors

duncanspumpkin avatar ericlemanissier avatar flexferrum avatar gracicot avatar jpcima avatar markazmierczak avatar martinmoene avatar mjacobse avatar pleroux0 avatar striezel avatar vvish avatar wkennington avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

span-lite's Issues

Imply span_FEATURE_MAKE_SPAN from span_FEATURE_NON_MEMBER_FIRST_LAST_SUB

Imply span_FEATURE_MAKE_SPAN when span_FEATURE_NON_MEMBER_FIRST_LAST_SUB is on, as the non-member functions first(), last() and subspan() require make_span().

Currently enabling first() etc. without enabling make_span() leads to #error.

Plan:

  • In code, imply span_FEATURE_MAKE_SPAN from span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
  • Document span_FEATURE_MAKE_SPAN, mentioning it is implied by span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
  • In document of span_FEATURE_NON_MEMBER_FIRST_LAST_SUB, mention it implies span_FEATURE_MAKE_SPAN

Originates from issue #32 .

error in finding as_bytes when byte-lite is present

I think you should do this in order to enable as_bytes function to your byte-lite library?

#if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
using span_lite::as_bytes;
using span_lite::as_writeable_bytes;
#endif

The original code doesn't have span_HAVE( NONSTD_BYTE ) and that causes me error in using as_bytes even though bite-lite exists.

Allow span(std::array<const T,N>) ?

span-lite release 0.1.0 allows the construction of a span from std::array with a const value type.

However this is not supported by p0122r7.

Keep an eye on this and if needed, decide to allow or not such a difference from std::span. If it's different from std::span, add a notice to the test specification.

See also thread [isocpp-lib] P0122R7 (span): element_type instead of value_type in constructor taking std::aray? of 28-Apr-18, 15:21.

Add span_FEATURE_WITH_CONTAINER

Add configuration flag span_FEATURE_WITH_CONTAINER to unconditionally control presence of constructors of the form span(with_container_t, ...).

Plan:

  • Add span_FEATURE_WITH_CONTAINER with priority above span_FEATURE_WITH_CONTAINER_TO_STD
  • Add span_FEATURE_WITH_CONTAINER to test/span-main.t.cpp
  • Document span_FEATURE_WITH_CONTAINER, mentioning it precedes over span_FEATURE_WITH_CONTAINER_TO_STD
  • In documentation of span_FEATURE_WITH_CONTAINER_TO_STD, mention span_FEATURE_WITH_CONTAINER takes precedence
  • Mention macro in table
  • Mention span_FEATURE_WITH_CONTAINER in test/CMakeLists.txt
  • Mention span_FEATURE_WITH_CONTAINER in test/t.bat, tg.bat, tc.bat

Originates from issue #32 .

Envisioned implementation:

#ifndef  span_FEATURE_WITH_CONTAINER
#ifdef   span_FEATURE_WITH_CONTAINER_TO_STD
# define span_FEATURE_WITH_CONTAINER  span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD )
#else
# define span_FEATURE_WITH_CONTAINER  0
#endif
#endif

Originates from issue #32 .

Construct span from a pair of iterators

The following code does not compile:

#include <vector>
#include <span>
#include <https://raw.githubusercontent.com/martinmoene/span-lite/master/include/nonstd/span.hpp>

#define s nonstd::span
// #define s std::span

void consume(s<int>);

int main () {
    std::vector a{1, 2, 3};

    consume(s(a.begin() + 1, a.end()));
}

Create span-lite

Overall

  • Code
  • Tests
  • Examples
  • Readme
  • CI: Appveyor
  • CI: Travis

Readme

  • Badge: Godbolt
  • Badge: Wandbox
  • Example usage
  • In a nutshell
  • License
  • Dependencies
  • Synopsis: Documentation of std::span
  • Synopsis: Non-standard extensions
  • Synopsis: Configuration
  • Reported to work with
  • Building the tests
  • Other implementations of span
  • Notes and references
  • Appendix

Later

  • Installation: As copied header
  • Installation: As external Git project
  • Installation: As CMake package
  • Installation: As Conan package

Tests don't build against libc++

Looks like libc++ doesn't like std::equal between volatile and non-volatile members in the test cases

In file included from /build/span-lite/test/span.t.cpp:11:
In file included from /build/span-lite/test/span-main.t.hpp:19:
In file included from /build/span-lite/include/nonstd/span.hpp:194:
/usr/include/c++/v1/algorithm:1325:14: error: no matching function for call to object of type 'std::__1::__equal_to<int, int>'
        if (!__pred(*__first1, *__first2))
             ^~~~~~
/usr/include/c++/v1/algorithm:1337:19: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *, std::__1::__equal_to<int, int> >' requested here
    return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
                  ^
/build/span-lite/test/span.t.cpp:441:18: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *>' requested here
    EXPECT( std::equal( x.begin(), x.end(), arr ) );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/usr/include/c++/v1/algorithm:682:10: note: candidate function not viable: 1st argument ('const volatile int') would lose volatile qualifier
    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
         ^
1 error generated.
make[2]: *** [test/CMakeFiles/span-lite-cpp98.t.dir/build.make:76: test/CMakeFiles/span-lite-cpp98.t.dir/span.t.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:134: test/CMakeFiles/span-lite-cpp98.t.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
/build/span-lite/test/span.t.cpp:89:99: warning: 'operator()' is deprecated: replace operator() with operator[] [-Wdeprecated-declarations]
        static void blow_iv(index_type i) { int arr[] = { 1, 2, 3, }; span<int> v( arr ); (void) v(i); }
                                                                                                  ^
/build/span-lite/include/nonstd/span.hpp:1067:5: note: 'operator()' has been explicitly marked deprecated here
    span_deprecated("replace operator() with operator[]")
    ^
/build/span-lite/include/nonstd/span.hpp:388:33: note: expanded from macro 'span_deprecated'
# define span_deprecated(msg) [[deprecated(msg)]]
                                ^
/build/span-lite/test/span.t.cpp:596:18: warning: 'operator()' is deprecated: replace operator() with operator[] [-Wdeprecated-declarations]
        EXPECT( v(i) == arr[i] );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/build/span-lite/include/nonstd/span.hpp:1067:5: note: 'operator()' has been explicitly marked deprecated here
    span_deprecated("replace operator() with operator[]")
    ^
/build/span-lite/include/nonstd/span.hpp:388:33: note: expanded from macro 'span_deprecated'
# define span_deprecated(msg) [[deprecated(msg)]]
                                ^
/build/span-lite/test/span.t.cpp:597:18: warning: 'operator()' is deprecated: replace operator() with operator[] [-Wdeprecated-declarations]
        EXPECT( w(i) == arr[i] );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/build/span-lite/include/nonstd/span.hpp:1067:5: note: 'operator()' has been explicitly marked deprecated here
    span_deprecated("replace operator() with operator[]")
    ^
/build/span-lite/include/nonstd/span.hpp:388:33: note: expanded from macro 'span_deprecated'
# define span_deprecated(msg) [[deprecated(msg)]]
                                ^
/build/span-lite/test/span.t.cpp:681:6: warning: 'operator()' is deprecated: replace operator() with operator[] [-Wdeprecated-declarations]
    v(1) = 22;
     ^
/build/span-lite/include/nonstd/span.hpp:1067:5: note: 'operator()' has been explicitly marked deprecated here
    span_deprecated("replace operator() with operator[]")
    ^
/build/span-lite/include/nonstd/span.hpp:388:33: note: expanded from macro 'span_deprecated'
# define span_deprecated(msg) [[deprecated(msg)]]
                                ^
/build/span-lite/test/span.t.cpp:682:6: warning: 'operator()' is deprecated: replace operator() with operator[] [-Wdeprecated-declarations]
    w(2) = 33;
     ^
/build/span-lite/include/nonstd/span.hpp:1067:5: note: 'operator()' has been explicitly marked deprecated here
    span_deprecated("replace operator() with operator[]")
    ^
/build/span-lite/include/nonstd/span.hpp:388:33: note: expanded from macro 'span_deprecated'
# define span_deprecated(msg) [[deprecated(msg)]]
                                ^
In file included from /build/span-lite/test/span.t.cpp:11:
In file included from /build/span-lite/test/span-main.t.hpp:19:
In file included from /build/span-lite/include/nonstd/span.hpp:194:
/usr/include/c++/v1/algorithm:1325:14: error: no matching function for call to object of type 'std::__1::__equal_to<int, int>'
        if (!__pred(*__first1, *__first2))
             ^~~~~~
/usr/include/c++/v1/algorithm:1337:19: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *, std::__1::__equal_to<int, int> >' requested here
    return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
                  ^
/build/span-lite/test/span.t.cpp:441:18: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *>' requested here
    EXPECT( std::equal( x.begin(), x.end(), arr ) );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/usr/include/c++/v1/algorithm:682:10: note: candidate function not viable: 1st argument ('const volatile int') would lose volatile qualifier
    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
         ^
1 error generated.
make[2]: *** [test/CMakeFiles/span-lite-cpp11.t.dir/build.make:76: test/CMakeFiles/span-lite-cpp11.t.dir/span.t.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:208: test/CMakeFiles/span-lite-cpp11.t.dir/all] Error 2
In file included from /build/span-lite/test/span.t.cpp:11:
In file included from /build/span-lite/test/span-main.t.hpp:19:
In file included from /build/span-lite/include/nonstd/span.hpp:194:
/usr/include/c++/v1/algorithm:1325:14: error: no matching function for call to object of type 'std::__1::__equal_to<int, int>'
        if (!__pred(*__first1, *__first2))
             ^~~~~~
/usr/include/c++/v1/algorithm:1337:19: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *, std::__1::__equal_to<int, int> >' requested here
    return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
                  ^
/build/span-lite/test/span.t.cpp:441:18: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *>' requested here
    EXPECT( std::equal( x.begin(), x.end(), arr ) );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/usr/include/c++/v1/algorithm:682:10: note: candidate function not viable: 1st argument ('const volatile int') would lose volatile qualifier
    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
         ^
1 error generated.
make[2]: *** [test/CMakeFiles/span-lite-cpp14.t.dir/build.make:76: test/CMakeFiles/span-lite-cpp14.t.dir/span.t.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:97: test/CMakeFiles/span-lite-cpp14.t.dir/all] Error 2
In file included from /build/span-lite/test/span.t.cpp:11:
In file included from /build/span-lite/test/span-main.t.hpp:19:
In file included from /build/span-lite/include/nonstd/span.hpp:194:
/usr/include/c++/v1/algorithm:1325:14: error: no matching function for call to object of type 'std::__1::__equal_to<int, int>'
        if (!__pred(*__first1, *__first2))
             ^~~~~~
/usr/include/c++/v1/algorithm:1337:19: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *, std::__1::__equal_to<int, int> >' requested here
    return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
                  ^
/build/span-lite/test/span.t.cpp:441:18: note: in instantiation of function template specialization 'std::__1::equal<const volatile int *, int *>' requested here
    EXPECT( std::equal( x.begin(), x.end(), arr ) );
                 ^
/build/span-lite/test/lest_cpp03.hpp:257:28: note: expanded from macro 'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/usr/include/c++/v1/algorithm:682:10: note: candidate function not viable: 1st argument ('const volatile int') would lose volatile qualifier
    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
         ^
5 warnings and 1 error generated.
make[2]: *** [test/CMakeFiles/span-lite-cpp17.t.dir/build.make:76: test/CMakeFiles/span-lite-cpp17.t.dir/span.t.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:171: test/CMakeFiles/span-lite-cpp17.t.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

depending on string pulls in heavy dependiencies

Hello,

I just realized you pulled in dependencies on string + shift operators. I am not really happy about that, as this will add alot of code, especially if you otherwise dont depend on this class, along with heap allocations.

I can create a pull request, replacing those dependencies with code using std::to_chars or std::sprintf working purely on the stack. This seems to be the better approach to me, would you agree and accept this?

[Readme] Use #include in code on Godbolt

For example:

#include "https://raw.githubusercontent.com/martinmoene/span-lite/master/include/nonstd/span.hpp"

main()
{
    int a[] = {1,2,3,};
    nonstd::span<int> spn( a );

    as_bytes( spn );
}

Add span_FEATURE_MAKE_SPAN

Add configuration flag span_FEATURE_MAKE_SPAN to unconditionally control presence of make_span()

Plan:

  • Add span_FEATURE_MAKE_SPAN with priority above span_FEATURE_MAKE_SPAN_TO_STD
  • Add span_FEATURE_MAKE_SPAN to test/span-main.t.cpp
  • Document span_FEATURE_MAKE_SPAN, mentioning it precedes over span_FEATURE_MAKE_SPAN_TO_STD
  • In documentation of span_FEATURE_MAKE_SPAN_TO_STD, mention span_FEATURE_MAKE_SPAN takes precedence
  • Mention macro in table
  • Mention span_FEATURE_MAKE_SPAN in test/CMakeLists.txt
  • Mention span_FEATURE_MAKE_SPAN in test/t.bat, tg.bat, tc.bat

Originates from issue #32 .

Envisioned implementation:

#ifndef  span_FEATURE_MAKE_SPAN
#ifdef   span_FEATURE_MAKE_SPAN_TO_STD
# define span_FEATURE_MAKE_SPAN  span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD )
#else
# define span_FEATURE_MAKE_SPAN  0
#endif
#endif

Review span in face of p1024 and Tristan Brindle's span implementation

References:

Plan:

  • Add front() and back() member functions (p1024)
  • Mark empty() as [[nodiscard]] (p1024)
  • Add (macro for) deprecation messages
  • Remove/deprecate operator() for element access (p1024)
  • Rename namespace details to detail.
  • Rename span_CONFIG_PROVIDE... to span_FEATURE....
  • Rename span_CONFIG_CONTRACT_CHECK() to span_CONTRACT_CHECK().
  • Rename to span_FEATURE_MEMBER_BACK_FRONT, span_FEATURE_MEMBER_SWAP.
  • Make sure span_HAVE_* are defined.
  • Name exception contract_violation, function report_contract_violation(....): throw, or terminate.
  • Fix span_CONFIG_CONTRACT_CHECK for contract-violation-terminates, issue #15.
  • span_constexpr_exp: constexpr (elided), or span_constexpr14.
  • span_constexpr_ens: constexpr (elided), or span_constexpr14.
  • Add contract non-empty to front(), back()
  • Add member at(index_type).
  • Add non-member versions of first(), last() and subspan().
  • Allow for index_type to be unsigned/size_t (p1089), see #21

Deferred to issue #30:

  • Use feature test macros: defined(__cpp_deduction_guides) etc.
  • Differentiate storage for dynamic, static extent.
  • Structured bindings support for fixed-size spans (only non-dynamically-sized spans) (p1024)
  • Allow also for Extent to be unsigned with dynamic_extent numeric_limits<index_type>::max() (p1089)?

Review span in face of p1024, p1089, p1872 (Continued from #14)

References:

Plan:

  • Rename as_writeable_bytes() to as_writable_bytes() (in r7, thanks to @nolange, see below)
  • Structured bindings support for fixed-size spans (only non-dynamically-sized spans) (p1024)
  • Change default of span_FEATURE_COMPARISON to 0 (p1085)
  • Change default of span_CONFIG_SIZE_TYPE to std::size_t (p1089)
  • Change default of span_CONFIG_EXTENT_TYPE to std::size_t (p1089)
  • Allow also for Extent to be unsigned with dynamic_extent numeric_limits<index_type>::max() or static_cast<extent_t>(-1); (p1089)
  • Rename index_type to size_type (p1872)

  • Differentiate storage for dynamic, static extent: moved to #8 (duplicate #47)
  • Use feature test macros: defined(__cpp_deduction_guides) etc.: moved to #48

Warning Wtype-limits since gcc 10.2

Enabling -Wextra leads to several warnings inside span-lite since gcc 10.2, for example (https://godbolt.org/z/7GrYsM):

<source>:1084:25: warning: comparison of unsigned expression in '>= 0' is always true [-Wtype-limits]
 1084 |         span_EXPECTS( 0 <= idx && idx < size() );
      | 

In many places, an index of size_type is checked to be not negative, which results in this warning if the size_type is an unsigned type (which is the default). If size_type is configured to be signed, the check 0 <= idx is of course reasonable. Not quite sure what the best approach would be. Write a helper template function is_negative that checks the type for signedness first and only then performs the check maybe? Or disable the warning entirely, but maybe it could be useful for other cases?

integral constant overflow when building unit tests with MSVC

span-lite\include\nonstd\span.hpp(1302): warning C4307: '*': integral constant overflow
span-lite\test\span.t.cpp(1127): note: see reference to function template instantiation 'nonstd::span_lite::span<const std::byte,18446744073709551615>
 nonstd::span_lite::as_bytes<int,18446744073709551615>(nonstd::span_lite::span<int,18446744073709551615>)' being compiled
span-lite\include\nonstd\span.hpp(1314): warning C4307: '*': integral constant overflow
span-lite\test\span.t.cpp(1148): note: see reference to function template instantiation 'nonstd::span_lite::span<byte,18446744073709551615> nonstd::span_lite::as_writable_bytes<int,18446744073709551615>(nonstd::span_lite::span<int,18446744073709551615>)' being compiled

This appears to just be MSVC being a bit dumb & unable to figure out you never actually multiply with overflow. One solution is to just move the byte extent computation into a helper template struct:

template <typename T, extent_t Extent> struct BytesExtent {
  static constexpr auto value = span_sizeof(T) * Extent;
};

template <typename T> struct BytesExtent<T, dynamic_extent> {
  static constexpr auto value = dynamic_extent;
};

template <typename T, extent_t Extent>
static constexpr auto BytesExtent_v = BytesExtent<T, Extent>::value;

Then you just use BytesExtent_v<T, Extent> everywhere instead of the runtime conditional.

Fix operator==()

Change

#if span_CONFIG_PROVIDE_SAME
    return
        same( l, r ) ||
        ( l.size() == r.size() && ( static_cast<void const*>( l.begin() ) == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) ) );
#else
    return
        ( l.size() == r.size() && ( l.begin() == r.begin() || std::equal( l.begin(), l.end(), r.begin() ) ) );
#endif

to

    return
#if span_CONFIG_PROVIDE_SAME
        same( l, r ) ||
#endif
        ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) );

Inconsitent behaviors with C array and make_span return type

Hello, please see the following:

static_assert(std::is_same<decltype(make_span(std::declval<int[5]>())),span<const int>>::value, "make_span Broken");
static_assert(std::is_same<decltype(make_span(std::declval<int(&)[5]>())),span<int,5>>::value, "make_span Broken");
static_assert(std::is_same<decltype(make_span(std::declval<const int[5]>())),span<const int,5>>::value, "make_span Broken");
static_assert(std::is_same<decltype(make_span(std::declval<const int(&)[5]>())),span<const int,5>>::value, "make_span Broken");

The first case returns a span with dynamic extent, while the other 3 return a span with a fixed size extent.

While non-const rvalue reference to C arrays almost never appear anywhere, this is a minor inconsistency and looks like a bug?

index_type ptr_diff

I glanced at p0122r6.pdf and could not find an answer. size() returns a type index_type which is a ptrdiff_t.
ptrdiff_t is signed, so for code that does something similar to:

if ( std::vector::size() != std::span::size() )

I will get a compiler warning about comparing signed and unsigned. I do not understand why a span size could be negative.

What is the rational for using ptrdiff_t here? Given that some of span's constructor can accept size_t that means one could create a span with a size bigger than what span::size() could actually return ?

I understand this has nothing to do with your implementation but was wondering if you had any comment about this. I assume usage of ptrdiff_t is required by math is performed on pointers?

span_FEATURE_*_TO_STD does not do what is advertised

Example:

-Dspan_FEATURE_MAKE_SPAN_TO_STD=14
Define this to the highest C++ language version for which to provide creator functions nonstd::make_span(). Default is undefined.

  1. I do not understand why? It sounds like defining this to "14" leads to make_span available in 98, 11, 14 and not available in 17, 20, ... Why would one want this?
  2. It does not work like that: #define span_IN_STD( v ) ( (v) == 98 || (v) >= span_CPLUSPLUS_V )
  • When defined to 98 it will always be available
  • Otherwise see 1.

Is this intentional? If so, can this be documented?
Why not make it simply a ON/OFF define? The build system can then be used to provide those in a more transparent way. (e.g. CMake generator expressions)

Does not build with clang++-6.0

Hello, the tests won't build with clang-6.0, problem is the C++17 configuration in combination with a C++ Library that provides std::byte.
First the issue:

[ 33%] Building CXX object test/CMakeFiles/span-main-cpp17.t.dir/span.t.cpp.o
In file included from /home/lano/git/span-lite/test/span.t.cpp:11:
In file included from /home/lano/git/span-lite/test/span-main.t.hpp:14:
/home/lano/git/span-lite/test/lest_cpp03.hpp:648:53: error: call to function
      'operator<<' that is neither visible in the template definition nor found
      by argument-dependent lookup
        std::ostringstream os; os << std::boolalpha << value;
                                                    ^
/home/lano/git/span-lite/test/lest_cpp03.hpp:674:29: note: in instantiation of
      member function 'lest::string_maker<std::byte>::to_string' requested here
    return string_maker<T>::to_string( value );
                            ^
/home/lano/git/span-lite/test/lest_cpp03.hpp:715:34: note: in instantiation of
      function template specialization 'lest::to_string<std::byte>' requested
      here
    std::ostringstream os; os << to_string( lhs ) << " " << op << " " <...
                                 ^
/home/lano/git/span-lite/test/lest_cpp03.hpp:727:92: note: in instantiation of
      function template specialization 'lest::to_string<std::byte, std::byte>'
      requested here
  ...operator==( R const & rhs ) { return result( lhs == rhs, to_string( lhs...
                                                              ^
/home/lano/git/span-lite/test/span.t.cpp:992:19: note: in instantiation of
      function template specialization 'lest::expression_lhs<const std::byte
      &>::operator==<std::byte>' requested here
    EXPECT( vb[0] == b[0] );
                  ^
/home/lano/git/span-lite/test/lest_cpp03.hpp:229:28: note: expanded from macro
      'EXPECT'
# define EXPECT            lest_EXPECT
                           ^
/home/lano/git/span-lite/test/span-main.t.hpp:40:23: note: 'operator<<' should
      be declared prior to the call site
inline std::ostream & operator<<( std::ostream & os, std::byte b )

I used these flags for configuring, clang is version 6.0, libstdc++ is version 7.3.0.
cmake -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_COMPILER=clang++-6.0 -DCMAKE_C_COMPILER=clang-6.0..

Same issue persists if I tell clang to use libc++, which might be a useful additional configuration for the automated tests?
I generally tend to use IPO for testing as this might cause additional warnings or errors, roughly thats what I had to do:

apt-get install clang++-6.0 libc++abi-dev libc++-dev
cmake -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_COMPILER=clang++-6.0 -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_FLAGS=-stdlib=libc++ ..

Failed to build release 0.5.0 with gcc 5.4 and default `-std` setting

Here is the diagnostic:

[ 50%] Building CXX object CMakeFiles/test_package.dir/test_package.cpp.o
In file included from /tmp/c3ipr/pr_66_1_0_0/test_package/test_package.cpp:1:0:
/tmp/c3ipr/pr_66_1_0_0/.conan/data/span-lite/0.5.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/nonstd/span.hpp: In function ‘void nonstd::span_lite::detail::throw_out_of_range(nonstd::span_lite::index_t, nonstd::span_lite::index_t)’:
/tmp/c3ipr/pr_66_1_0_0/.conan/data/span-lite/0.5.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/nonstd/span.hpp:614:11: error: ‘out_of_range’ is not a member of ‘std’
     throw std::out_of_range( "span::at(): index outside span" );

More details here: conan-io/conan-center-index#66 (comment)

A few small suggestions

Great job. Thanks for creating & releasing this.
Have you considered offering it for use in libc++/clang?
It would be good if you could add the static size optimisation (at some point).

I have been experimenting with it & testing it with Clang 6.0 & C++17.

Here’s my feedback & suggestions:

  • Add #include <algorithm> (for lexicographical_compare).
  • The with_container_t stuff appears redundant (with Clang 6.0 & C++17).
  • In namespace nonstd add using span_lite::as_bytes; and using span_lite::as_writeable_bytes; (after line 932).
  • The operator== fails to compile with:
    static const uint8_t data[] = { 0,1,2,3,4,5,6,7,8,9,10 };
    span<uint8_t const> span_data(data);
    assert(make_span(data) == span_data);	// Compile error

I fixed it by adding template<class T> struct is_span_oracle<span<T>> : std::true_type {}; (by the current is_span_oracle) and changed operator==, != etc. to something like:

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator==(span<T1, L1> l, span<T2, L2> r)
    { return (l.cbegin() == r.cbegin() && l.size() == r.size()) ||
             equal(l.cbegin(), l.cend(), r.cbegin(), r.cend()); }

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator<(span<T1, L1> l, span<T2, L2> r)
    { return lexicographical_compare(l.cbegin(), l.cend(), r.cbegin(), r.cend()); }

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator!=(span<T1, L1> l, span<T2, L2> r)	{ return !(l == r); }

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator<=(span<T1, L1> l, span<T2, L2> r)	{ return !(r < l); }

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator>(span<T1, L1> l, span<T2, L2> r)	{ return (r < l); }

template<class T1, index_t L1, class T2, index_t L2> inline constexpr bool
operator>=(span<T1, L1> l, span<T2, L2> r)	{ return !(l < r); }
  • The as_bytes & as_writeable_bytes have a mistake in their disabled lines (closing paren in wrong plac)e:
    return { reinterpret_cast< std::byte const * >( spn.data(), spn.size_bytes() ) };
    should be:
    return { reinterpret_cast<std::byte const*>(spn.data()), spn.size_bytes() };
                                                          ^
    And
    return { reinterpret_cast< std::byte * >( spn.data(), spn.size_bytes() ) };
    should be:
    return { reinterpret_cast<std::byte*>(spn.data()), spn.size_bytes() };
                                                    ^
  • I added the following helpers along with the make_span functions:
template<class T> inline constexpr auto
byte_span(T& t) noexcept
    { return span<byte, sizeof(t)>(reinterpret_cast<byte*>(&t), sizeof(t)); }

template<class T> inline constexpr auto
byte_span(T const& t) noexcept
    { return span<byte const, sizeof(t)>(reinterpret_cast<byte const*>(&t), sizeof(t)); }
  • I also added cdata, front & back member functions (with the obvious impls).
  • Additionally I added the following (as C++ has no operator===):
    template<class Span2 = span<T, Extent>>
    constexpr bool same(Span2 s) const noexcept
    {
        return static_cast<void const*>(data()) == s.data() && size() == s.size();
    }

Compile errors with clang10 and libc++

When trying to use your library with clang10 and libc++ and c++2a I get some compile errors for missing function-like macro span_HAVE. It works with clang9 and libc++ and c++2a though.
Godbolt showcasing the issue (against 0.7.0, but errors also relevant on master branch): https://godbolt.org/z/yWWR6Z

Compile errors:


x86-64 clang 10.0.0 (Editor #1, Compiler #1) C++
x86-64 clang 10.0.0
-stdlib=libc++ -std=c++2a
1
<Compilation failed>
x86-64 clang 10.0.0 - 1422ms
#1 with x86-64 clang 10.0.0
nonstd/span.hpp:1523:61: error: function-like macro 'span_HAVE' is not defined

#if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) )

                                                            ^

nonstd/span.hpp:1553:5: error: function-like macro 'span_HAVE' is not defined

#if span_HAVE( STRUCT_BINDING )

Get a constant sized subspan

Just a question on preferred usage: Assume I have a memory which contains a number of arrays of fixed size. I get this memory as a span<T> and the array count as a runtime parameter. Hence the span size is a runtime parameter. Now I want to Process this memory chunk 1 array at a time:

constexpr size_t arraySize = ...;
for(int i=0; i<numArrays; i++) {
  auto subArray = mySpan.subspan(arraySize*i, arraySize);
  // work on subArray
}

Although arraySize is a compile time constant and could be filled into the subArray template param, subspan does not do/allow that.

Questions:

  1. How to solve this task in general (the preferred way)?
  2. Can I make a subspan with a constant size from a variable-sized span?
  3. Is there any advantage in having a constant size?

Update to proposal p0122r7

p0122 - span: bounds-safe views for sequences of objects

See also Reddit: 2018 San Diego ISO C++ Committee Trip Report.

See also 2019-02 Kona ISO C++ Committee Trip Report.

Plan:


size(spn), ssize(spn)

In namespace nonstd::span_lite:

namespace nonstd { namespace span_lite {

template< class T, extent_t Extent /*= dynamic_extent*/ >
span_constexpr std::size_t size( span<T,Extent> const & spn )
{
    return static_cast<std::size_t>( spn.size() );
}

template< class T, extent_t Extent /*= dynamic_extent*/ >
span_constexpr std::ptrdiff_t ssize( span<T,Extent> const & spn )
{
    return static_cast<std::ptrdiff_t>( spn.size() );
}
}} // namespace

namespace nonstd { 
    using span_lite::size;
    using span_lite::ssize;
}

span_HAVE_DEDUCTION_GUIDES deduction on MSVC fails

span_HAVE_DEDUCTION_GUIDES is defined like this:

#define span_HAVE_DEDUCTION_GUIDES         (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 999 ))

which excludes the feature on all MSVC versions... even though right above a comment notes:

// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7

I can only find two other feature tests that use span_COMPILER_MSVC_VERSION rather than span_COMPILER_MSVC_VER.
Would it be acceptable to just change those?

e.g.

--- a/span.hpp
+++ b/span.hpp
@@ -243,7 +241,7 @@ using std::span;
 # pragma GCC   diagnostic ignored "-Wundef"
 # define span_RESTORE_WARNINGS()   _Pragma( "GCC diagnostic pop" )
 
-#elif span_COMPILER_MSVC_VERSION >= 140
+#elif span_COMPILER_MSVC_VER >= 1900
 # define span_DISABLE_MSVC_WARNINGS(codes)  __pragma(warning(push))  __pragma(warning(disable: codes))
 # define span_RESTORE_WARNINGS()            __pragma(warning(pop ))
 
@@ -311,7 +309,7 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 )
 
 // MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
 
-#define span_HAVE_DEDUCTION_GUIDES         (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 999 ))
+#define span_HAVE_DEDUCTION_GUIDES         (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 ))
 
 // Presence of C++ library features:
 
@@ -319,7 +317,7 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 )
 #define span_HAVE_ARRAY                     span_CPP11_110
 #define span_HAVE_BYTE                      span_CPP17_000
 #define span_HAVE_CONDITIONAL               span_CPP11_120
-#define span_HAVE_CONTAINER_DATA_METHOD    (span_CPP11_140 || ( span_COMPILER_MSVC_VERSION >= 90 && span_HAS_CPP0X ))
+#define span_HAVE_CONTAINER_DATA_METHOD    (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X ))
 #define span_HAVE_DATA                      span_CPP17_000
 #define span_HAVE_LONGLONG                  span_CPP11_80
 #define span_HAVE_REMOVE_CONST              span_CPP11_110

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.