diff --git a/dumux/common/CMakeLists.txt b/dumux/common/CMakeLists.txt index e28f1c1fb6accd4f5b4db91cabad5cbfeef9bbdc..f7fe41c5df1edd19a1037a02ce1f7bd21cbff142 100644 --- a/dumux/common/CMakeLists.txt +++ b/dumux/common/CMakeLists.txt @@ -17,6 +17,7 @@ doubleexpintegrationconstants.hh doubleexpintegrator.hh dumuxmessage.hh entitymap.hh +enumerate.hh exceptions.hh fixedlengthspline_.hh fvproblem.hh diff --git a/dumux/common/enumerate.hh b/dumux/common/enumerate.hh new file mode 100644 index 0000000000000000000000000000000000000000..d501cde0ab3c1044cd4367c2783f6900126a2d3b --- /dev/null +++ b/dumux/common/enumerate.hh @@ -0,0 +1,64 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief A Python-like enumerate function + */ + +#ifndef DUMUX_COMMON_ENUMERATE_HH +#define DUMUX_COMMON_ENUMERATE_HH + +#include <tuple> + +namespace Dumux { + +/*! + * \brief A Python-like enumerate function + * \param iterable Some iterable type with begin/end (e.g. std::vector) + * \note From Nathan Reed (CC BY 4.0): http://reedbeta.com/blog/python-like-enumerate-in-cpp17/ + * + * Usage example: for (const auto& [i, item] : enumerate(list)) + */ +template <typename Range, + typename RangeIterator = decltype(std::begin(std::declval<Range>())), + typename = decltype(std::end(std::declval<Range>()))> +constexpr auto enumerate(Range&& iterable) +{ + struct Iterator + { + std::size_t i; + RangeIterator iter; + bool operator != (const Iterator & other) const { return iter != other.iter; } + void operator ++ () { ++i; ++iter; } + auto operator * () const { return std::tie(i, *iter); } + }; + + struct Iteratable + { + Range iterable; + auto begin() { return Iterator{ 0, std::begin(iterable) }; } + auto end() { return Iterator{ 0, std::end(iterable) }; } + }; + + return Iteratable{ std::forward<Range>(iterable) }; +} + +} // end namespace Dumux + +#endif diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt index 68b481a963e0e524456015771aa2e1d31662a037..7ad9b6ead196b00d9c2c7e48f4a96404266c1cbf 100644 --- a/test/common/CMakeLists.txt +++ b/test/common/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(timeloop) add_subdirectory(typetraits) dumux_add_test(SOURCES test_partial.cc LABELS unit) +dumux_add_test(SOURCES test_enumerate.cc LABELS unit) diff --git a/test/common/test_enumerate.cc b/test/common/test_enumerate.cc new file mode 100644 index 0000000000000000000000000000000000000000..c8c5790afc76a6bb5c8900d31267800cc527786e --- /dev/null +++ b/test/common/test_enumerate.cc @@ -0,0 +1,21 @@ +#include <config.h> + +#include <vector> +#include <numeric> + +#include <dune/common/exceptions.hh> +#include <dumux/common/enumerate.hh> + +int main(int argc, char* argv[]) { + + using namespace Dumux; + + std::vector<std::size_t> vec(20); + std::iota(vec.begin(), vec.end(), 0); + + for (const auto& [i, item] : enumerate(vec)) + if (i != item) + DUNE_THROW(Dune::Exception, "Wrong index!"); + + return 0; +}