From 5f9d4020042d99b294de29093e3309c7007fa1ac Mon Sep 17 00:00:00 2001 From: Sam Yates <yates@cscs.ch> Date: Mon, 3 Apr 2017 18:45:51 +0200 Subject: [PATCH] Bug fix: crash on indirect test (#218) * Bug fix: crash on indirect test * Simplify indirect overloads, add nomove/nocopy tests --- src/util/indirect.hpp | 13 ++++++----- tests/unit/test_transform.cpp | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/util/indirect.hpp b/src/util/indirect.hpp index 5a9bb5b4..1e4dbba8 100644 --- a/src/util/indirect.hpp +++ b/src/util/indirect.hpp @@ -8,6 +8,8 @@ * Implemented as a transform view of the index map. */ +#include <utility> + #include <util/deduce_return.hpp> #include <util/transform.hpp> #include <util/meta.hpp> @@ -23,8 +25,9 @@ namespace impl { struct indirect_accessor { using reference = typename util::sequence_traits<Data>::reference; - Data& data; - indirect_accessor(Data& data): data(data) {} + Data data; + template <typename X> + indirect_accessor(X&& data): data(std::forward<X>(data)) {} template <typename I> reference operator()(const I& i) const { return data[i]; } @@ -33,11 +36,11 @@ namespace impl { template <typename RASeq, typename Seq> auto indirect_view(RASeq& data, const Seq& index_map) -DEDUCED_RETURN_TYPE(transform_view(index_map, impl::indirect_accessor<RASeq>(data))); +DEDUCED_RETURN_TYPE(transform_view(index_map, impl::indirect_accessor<RASeq&>(data))); template <typename RASeq, typename Seq> -auto indirect_view(const RASeq& data, const Seq& index_map) -DEDUCED_RETURN_TYPE(transform_view(index_map, impl::indirect_accessor<const RASeq>(data))); +auto indirect_view(RASeq&& data, const Seq& index_map) +DEDUCED_RETURN_TYPE(transform_view(index_map, impl::indirect_accessor<RASeq>(std::move(data)))); } // namespace util } // namespace mc diff --git a/tests/unit/test_transform.cpp b/tests/unit/test_transform.cpp index 33d1522e..ab48a1cd 100644 --- a/tests/unit/test_transform.cpp +++ b/tests/unit/test_transform.cpp @@ -9,6 +9,8 @@ #include <util/span.hpp> #include <util/transform.hpp> +#include "common.hpp" + using namespace nest::mc; TEST(transform, transform_view) { @@ -99,6 +101,45 @@ TEST(indirect, fwd_index) { EXPECT_EQ(expected, result); } +TEST(indirect, nocopy) { + const testing::nocopy<double> data[6] = {10., 11., 12., 13., 14., 15.}; + unsigned map_reverse[6] = {5, 4, 3, 2, 1, 0}; + auto reversed = util::indirect_view(data, map_reverse); + + std::vector<double> expected = {15., 14., 13., 12., 11., 10.}; + std::vector<double> result; + for (auto& elem: reversed) { result.push_back(elem.value); } + EXPECT_EQ(expected, result); + + unsigned map_evens[3] = {0, 2, 4}; + auto even_reversed = util::indirect_view(reversed, map_evens); + + expected = {15., 13., 11.}; + result.clear(); + for (auto& elem: even_reversed) { result.push_back(elem.value); } + EXPECT_EQ(expected, result); +} + +TEST(indirect, nomove) { + testing::nomove<double> data[6]; + for (unsigned i=0; i<util::size(data); ++i) data[i].value = 10.+i; + unsigned map_reverse[6] = {5, 4, 3, 2, 1, 0}; + auto reversed = util::indirect_view(data, map_reverse); + + std::vector<double> expected = {15., 14., 13., 12., 11., 10.}; + std::vector<double> result; + for (auto& elem: reversed) { result.push_back(elem.value); } + EXPECT_EQ(expected, result); + + unsigned map_evens[3] = {0, 2, 4}; + auto even_reversed = util::indirect_view(reversed, map_evens); + + expected = {15., 13., 11.}; + result.clear(); + for (auto& elem: even_reversed) { result.push_back(elem.value); } + EXPECT_EQ(expected, result); +} + TEST(indirect, modifying) { unsigned map1[] = {0, 2, 4, 1, 3, 0}; unsigned map2[] = {0, 1, 1, 1, 2}; -- GitLab