mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Add a copy() function for span.
This commit is contained in:
parent
2df9f85385
commit
d2dafe2ddf
@ -10,6 +10,7 @@ set(GSL_HEADERS
|
||||
"gsl/multi_span"
|
||||
"gsl/span"
|
||||
"gsl/string_span"
|
||||
"gsl/gsl_algorithm"
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
61
gsl/gsl_algorithm
Normal file
61
gsl/gsl_algorithm
Normal file
@ -0,0 +1,61 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef GSL_ALGORITHM_H
|
||||
#define GSL_ALGORITHM_H
|
||||
|
||||
#include "span"
|
||||
#include <algorithm>
|
||||
|
||||
#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
|
||||
|
||||
// blanket turn off warnings from CppCoreCheck for now
|
||||
// so people aren't annoyed by them when running the tool.
|
||||
// more targeted suppressions will be added in a future update to the GSL
|
||||
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
template <class SrcElementType, std::ptrdiff_t SrcExtent,
|
||||
class DestElementType, std::ptrdiff_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());
|
||||
std::copy_n(src.data(), src.size(), dest.data());
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GSL_ALGORITHM_H
|
@ -52,3 +52,5 @@ add_gsl_test(assertion_tests)
|
||||
add_gsl_test(utils_tests)
|
||||
add_gsl_test(owner_tests)
|
||||
add_gsl_test(byte_tests)
|
||||
add_gsl_test(algorithm_tests)
|
||||
|
||||
|
209
tests/algorithm_tests.cpp
Normal file
209
tests/algorithm_tests.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <UnitTest++/UnitTest++.h>
|
||||
#include <gsl/gsl_algorithm>
|
||||
|
||||
#include <array>
|
||||
|
||||
using namespace std;
|
||||
using namespace gsl;
|
||||
|
||||
SUITE(copy_tests)
|
||||
{
|
||||
|
||||
TEST(same_type)
|
||||
{
|
||||
// dynamic source and destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<int, 10> dst{};
|
||||
|
||||
span<int> src_span(src);
|
||||
span<int> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// static source and dynamic destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<int, 10> dst{};
|
||||
|
||||
span<int, 5> src_span(src);
|
||||
span<int> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// dynamic source and static destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<int, 10> dst{};
|
||||
|
||||
span<int> src_span(src);
|
||||
span<int, 10> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// static source and destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<int, 10> dst{};
|
||||
|
||||
span<int, 5> src_span(src);
|
||||
span<int, 10> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(compatible_type)
|
||||
{
|
||||
// dynamic source and destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<char, 10> dst{};
|
||||
|
||||
span<int> src_span(src);
|
||||
span<char> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// static source and dynamic destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<char, 10> dst{};
|
||||
|
||||
span<int, 5> src_span(src);
|
||||
span<char> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// dynamic source and static destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<char, 10> dst{};
|
||||
|
||||
span<int> src_span(src);
|
||||
span<char, 10> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// static source and destination span
|
||||
{
|
||||
std::array<int, 5> src{1, 2, 3, 4, 5};
|
||||
std::array<char, 10> dst{};
|
||||
|
||||
span<int, 5> src_span(src);
|
||||
span<char, 10> dst_span(dst);
|
||||
|
||||
copy(src_span, dst_span);
|
||||
copy(src_span, dst_span.subspan(src_span.size()));
|
||||
|
||||
for (std::size_t i = 0; i < src.size(); ++i) {
|
||||
CHECK(dst[i] == src[i]);
|
||||
CHECK(dst[i + src.size()] == src[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
TEST(incompatible_type)
|
||||
{
|
||||
std::array<int, 4> src{1, 2, 3, 4};
|
||||
std::array<int*, 12> dst{};
|
||||
|
||||
span<int> src_span_dyn(src);
|
||||
span<int, 4> src_span_static(src);
|
||||
span<int*> dst_span_dyn(dst);
|
||||
span<int*, 4> dst_span_static(dst);
|
||||
|
||||
// every line should produce a compilation error
|
||||
copy(src_span_dyn, dst_span_dyn);
|
||||
copy(src_span_dyn, dst_span_static);
|
||||
copy(src_span_static, dst_span_dyn);
|
||||
copy(src_span_static, dst_span_static);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(small_destination_span)
|
||||
{
|
||||
std::array<int, 12> src{1, 2, 3, 4};
|
||||
std::array<int, 4> dst{};
|
||||
|
||||
span<int> src_span_dyn(src);
|
||||
span<int, 12> src_span_static(src);
|
||||
span<int> dst_span_dyn(dst);
|
||||
span<int, 4> dst_span_static(dst);
|
||||
|
||||
CHECK_THROW(copy(src_span_dyn, dst_span_dyn), fail_fast);
|
||||
CHECK_THROW(copy(src_span_dyn, dst_span_static), fail_fast);
|
||||
CHECK_THROW(copy(src_span_static, dst_span_dyn), fail_fast);
|
||||
|
||||
#ifdef CONFIRM_COMPILATION_ERRORS
|
||||
copy(src_span_static, dst_span_static);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, const char* []) { return UnitTest::RunAllTests(); }
|
Loading…
Reference in New Issue
Block a user