Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
95f15540
Commit
95f15540
authored
Aug 01, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement C++20 std::span replacement
parent
3b0d45ef
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
349 additions
and
0 deletions
+349
-0
libcaf_core/caf/span.hpp
libcaf_core/caf/span.hpp
+232
-0
libcaf_core/test/span.cpp
libcaf_core/test/span.cpp
+117
-0
No files found.
libcaf_core/caf/span.hpp
0 → 100644
View file @
95f15540
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <array>
#include <type_traits>
#include "caf/byte.hpp"
#include "caf/detail/type_traits.hpp"
namespace
caf
{
/// A C++11/14 drop-in replacement for C++20's `std::span` without support for
/// static extents.
template
<
class
T
>
class
span
{
public:
// -- member types -----------------------------------------------------------
using
element_type
=
T
;
using
value_type
=
typename
std
::
remove_cv
<
T
>::
type
;
using
index_type
=
size_t
;
using
difference_type
=
ptrdiff_t
;
using
pointer
=
T
*
;
using
const_pointer
=
const
T
*
;
using
reference
=
T
&
;
using
const_reference
=
T
&
;
using
iterator
=
pointer
;
using
const_iterator
=
const
pointer
;
using
reverse_iterator
=
std
::
reverse_iterator
<
iterator
>
;
using
const_reverse_iterator
=
std
::
reverse_iterator
<
const_iterator
>
;
// -- constructors, destructors, and assignment operators --------------------
constexpr
span
()
noexcept
:
begin_
(
nullptr
),
size_
(
0
)
{
// nop
}
constexpr
span
(
pointer
ptr
,
size_t
size
)
:
begin_
(
ptr
),
size_
(
size
)
{
// nop
}
constexpr
span
(
pointer
first
,
pointer
last
)
:
begin_
(
first
),
size_
(
static_cast
<
size_t
>
(
last
-
first
))
{
// nop
}
template
<
size_t
Size
>
constexpr
span
(
element_type
(
&
arr
)[
Size
])
noexcept
:
begin_
(
arr
),
size_
(
Size
)
{
// nop
}
template
<
class
C
,
class
E
=
detail
::
enable_if_t
<
detail
::
has_data_member
<
C
>
::
value
>>
span
(
C
&
xs
)
noexcept
:
begin_
(
xs
.
data
()),
size_
(
xs
.
size
())
{
// nop
}
constexpr
span
(
const
span
&
)
noexcept
=
default
;
span
&
operator
=
(
const
span
&
)
noexcept
=
default
;
// -- iterators --------------------------------------------------------------
constexpr
iterator
begin
()
const
noexcept
{
return
begin_
;
}
constexpr
iterator
cbegin
()
const
noexcept
{
return
begin_
;
}
constexpr
iterator
end
()
const
noexcept
{
return
begin
()
+
size_
;
}
constexpr
iterator
cend
()
const
noexcept
{
return
begin
()
+
size_
;
}
constexpr
reverse_iterator
rbegin
()
const
noexcept
{
return
reverse_iterator
{
end
()};
}
constexpr
reverse_iterator
crbegin
()
const
noexcept
{
return
reverse_iterator
{
end
()};
}
constexpr
reverse_iterator
rend
()
const
noexcept
{
return
reverse_iterator
{
begin
()};
}
constexpr
reverse_iterator
crend
()
const
noexcept
{
return
reverse_iterator
{
begin
()};
}
// -- element access ---------------------------------------------------------
constexpr
reference
operator
[](
size_t
index
)
const
noexcept
{
return
begin_
[
index
];
}
constexpr
reference
front
()
const
noexcept
{
return
*
begin_
;
}
constexpr
reference
back
()
const
noexcept
{
return
(
*
this
)[
size_
-
1
];
}
// -- properties -------------------------------------------------------------
constexpr
size_t
size
()
const
noexcept
{
return
size_
;
}
constexpr
size_t
size_bytes
()
const
noexcept
{
return
size_
*
sizeof
(
element_type
);
}
constexpr
bool
empty
()
const
noexcept
{
return
size_
==
0
;
}
constexpr
pointer
data
()
const
noexcept
{
return
begin_
;
}
// -- subviews ---------------------------------------------------------------
constexpr
span
subspan
(
size_t
offset
,
size_t
num_bytes
)
const
{
return
{
begin_
+
offset
,
num_bytes
};
}
constexpr
span
first
(
size_t
num_bytes
)
const
{
return
{
begin_
,
num_bytes
};
}
constexpr
span
last
(
size_t
num_bytes
)
const
{
return
subspan
(
size_
-
num_bytes
,
num_bytes
);
}
private:
// -- member variables -------------------------------------------------------
/// Points to the first element in the contiguous memory block.
pointer
begin_
;
/// Stores the number of elements in the contiguous memory block.
size_t
size_
;
};
template
<
class
T
>
auto
begin
(
const
span
<
T
>&
xs
)
->
decltype
(
xs
.
begin
())
{
return
xs
.
begin
();
}
template
<
class
T
>
auto
cbegin
(
const
span
<
T
>&
xs
)
->
decltype
(
xs
.
cbegin
())
{
return
xs
.
cbegin
();
}
template
<
class
T
>
auto
end
(
const
span
<
T
>&
xs
)
->
decltype
(
xs
.
end
())
{
return
xs
.
end
();
}
template
<
class
T
>
auto
cend
(
const
span
<
T
>&
xs
)
->
decltype
(
xs
.
cend
())
{
return
xs
.
cend
();
}
template
<
class
T
>
span
<
const
byte
>
as_bytes
(
span
<
T
>
xs
)
{
return
{
reinterpret_cast
<
const
byte
*>
(
xs
.
data
()),
xs
.
size_bytes
()};
}
template
<
class
T
>
span
<
byte
>
as_writable_bytes
(
span
<
T
>
xs
)
{
return
{
reinterpret_cast
<
byte
*>
(
xs
.
data
()),
xs
.
size_bytes
()};
}
/// Convenience function to make using `caf::span` more convenient without the
/// deduction guides.
template
<
class
T
>
auto
make_span
(
T
&
xs
)
->
span
<
detail
::
decay_t
<
decltype
(
xs
[
0
])
>>
{
return
{
xs
.
data
(),
xs
.
size
()};
}
/// Convenience function to make using `caf::span` more convenient without the
/// deduction guides.
template
<
class
T
>
span
<
T
>
make_span
(
T
*
first
,
size_t
size
)
{
return
{
first
,
size
};
}
/// Convenience function to make using `caf::span` more convenient without the
/// deduction guides.
template
<
class
T
>
span
<
T
>
make_span
(
T
*
first
,
T
*
last
)
{
return
{
first
,
last
};
}
}
// namespace caf
libcaf_core/test/span.cpp
0 → 100644
View file @
95f15540
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE span
#include "caf/span.hpp"
#include "caf/test/dsl.hpp"
#include <algorithm>
using
namespace
caf
;
namespace
{
using
i8_list
=
std
::
vector
<
int8_t
>
;
using
i16_list
=
std
::
vector
<
int16_t
>
;
template
<
class
T
,
class
U
>
bool
equal
(
const
T
&
xs
,
const
U
&
ys
)
{
return
xs
.
size
()
==
ys
.
size
()
&&
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
());
}
struct
fixture
{
i8_list
chars
{
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
i8_list
rchars
{
'f'
,
'e'
,
'd'
,
'c'
,
'b'
,
'a'
};
i16_list
shorts
{
1
,
2
,
4
,
8
,
16
,
32
,
64
};
i16_list
rshorts
{
64
,
32
,
16
,
8
,
4
,
2
,
1
};
};
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
span_tests
,
fixture
)
CAF_TEST
(
default
construction
)
{
span
<
int
>
xs
;
CAF_CHECK_EQUAL
(
xs
.
size
(),
0u
);
CAF_CHECK_EQUAL
(
xs
.
empty
(),
true
);
CAF_CHECK_EQUAL
(
xs
.
data
(),
nullptr
);
CAF_CHECK_EQUAL
(
xs
.
size_bytes
(),
0u
);
CAF_CHECK_EQUAL
(
xs
.
begin
(),
xs
.
end
());
CAF_CHECK_EQUAL
(
xs
.
cbegin
(),
xs
.
cend
());
CAF_CHECK_EQUAL
(
xs
.
rbegin
(),
xs
.
rend
());
CAF_CHECK_EQUAL
(
xs
.
crbegin
(),
xs
.
crend
());
CAF_CHECK_EQUAL
(
as_bytes
(
xs
).
size_bytes
(),
0u
);
CAF_CHECK_EQUAL
(
as_writable_bytes
(
xs
).
size_bytes
(),
0u
);
}
CAF_TEST
(
iterators
)
{
auto
xs
=
make_span
(
chars
);
CAF_CHECK
(
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
chars
.
begin
()));
CAF_CHECK
(
std
::
equal
(
xs
.
rbegin
(),
xs
.
rend
(),
rchars
.
begin
()));
auto
ys
=
make_span
(
shorts
);
CAF_CHECK
(
std
::
equal
(
ys
.
begin
(),
ys
.
end
(),
shorts
.
begin
()));
CAF_CHECK
(
std
::
equal
(
ys
.
rbegin
(),
ys
.
rend
(),
rshorts
.
begin
()));
}
CAF_TEST
(
subspans
)
{
auto
xs
=
make_span
(
chars
);
CAF_CHECK
(
equal
(
xs
.
first
(
6
),
xs
));
CAF_CHECK
(
equal
(
xs
.
last
(
6
),
xs
));
CAF_CHECK
(
equal
(
xs
.
subspan
(
0
,
6
),
xs
));
CAF_CHECK
(
equal
(
xs
.
first
(
3
),
i8_list
({
'a'
,
'b'
,
'c'
})));
CAF_CHECK
(
equal
(
xs
.
last
(
3
),
i8_list
({
'd'
,
'e'
,
'f'
})));
CAF_CHECK
(
equal
(
xs
.
subspan
(
2
,
2
),
i8_list
({
'c'
,
'd'
})));
}
CAF_TEST
(
free
iterator
functions
)
{
auto
xs
=
make_span
(
chars
);
CAF_CHECK_EQUAL
(
xs
.
begin
(),
begin
(
xs
));
CAF_CHECK_EQUAL
(
xs
.
cbegin
(),
cbegin
(
xs
));
CAF_CHECK_EQUAL
(
xs
.
end
(),
end
(
xs
));
CAF_CHECK_EQUAL
(
xs
.
cend
(),
cend
(
xs
));
}
CAF_TEST
(
as
bytes
)
{
auto
xs
=
make_span
(
chars
);
auto
ys
=
make_span
(
shorts
);
CAF_CHECK_EQUAL
(
as_bytes
(
xs
).
size
(),
chars
.
size
());
CAF_CHECK_EQUAL
(
as_bytes
(
ys
).
size
(),
shorts
.
size
()
*
2
);
CAF_CHECK_EQUAL
(
as_writable_bytes
(
xs
).
size
(),
chars
.
size
());
CAF_CHECK_EQUAL
(
as_writable_bytes
(
ys
).
size
(),
shorts
.
size
()
*
2
);
}
CAF_TEST
(
make_span
)
{
auto
xs
=
make_span
(
chars
);
auto
ys
=
make_span
(
chars
.
data
(),
chars
.
size
());
auto
zs
=
make_span
(
chars
.
data
(),
chars
.
data
()
+
chars
.
size
());
CAF_CHECK
(
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
chars
.
begin
()));
CAF_CHECK
(
std
::
equal
(
ys
.
begin
(),
ys
.
end
(),
chars
.
begin
()));
CAF_CHECK
(
std
::
equal
(
zs
.
begin
(),
zs
.
end
(),
chars
.
begin
()));
CAF_CHECK_EQUAL
(
end
(
xs
),
end
(
ys
));
CAF_CHECK_EQUAL
(
end
(
ys
),
end
(
zs
));
CAF_CHECK_EQUAL
(
begin
(
xs
),
begin
(
ys
));
CAF_CHECK_EQUAL
(
begin
(
ys
),
begin
(
zs
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment