From 3ee79191612e9226bb4d30af1f428b81a197e6ae Mon Sep 17 00:00:00 2001 From: Sam Yates <yates@cscs.ch> Date: Fri, 6 Jul 2018 16:39:35 +0200 Subject: [PATCH] Migrate source/build to c++14 (#522) * Update `CMakeLists.txt` for C++14 option. * Update to gcc 6 minimum. * Update travis CI from gcc-5 to gcc-6 * Use `std::..._t` style type traits, replacing `util::` aliases. * Use `std::cbegin`, `std::cend`, and `std::make_unique`, replacing `util::` versions. * Remove `DEDUCED_RETURN_TYPE` macros. * Remove redundant return type specifications. * Use correct ADL for `begin` and `end` in (almost all) the range utilities. * Remove redundant `mechinfo` ctor (aggregate initialization suffices). * Use lambda capture initializers where appropriate. * Use generic `std::equal_to`. * Use variable templates for `math::infinity` and `math::pi`. * Remove `enum_hash` workaround. * Use `""s` string literals where we were using our own `""_s` construction. * Use generic lambda for recursive lambda instead of `std::function` wrapper. * Use generic lambda for generic arithmetic tests. Fixes #358. --- .travis.yml | 6 +- CMakeLists.txt | 6 +- arbor/algorithms.hpp | 46 +++----- arbor/backends/builtin_mech_proto.hpp | 6 +- arbor/backends/gpu/shared_state.hpp | 3 +- arbor/backends/multicore/shared_state.hpp | 3 +- arbor/fvm_layout.cpp | 13 ++- arbor/fvm_layout.hpp | 14 +-- arbor/fvm_lowered_cell_impl.hpp | 5 +- arbor/math.hpp | 35 ++---- arbor/mechcat.cpp | 14 +-- arbor/memory/array.hpp | 14 +-- arbor/memory/array_view.hpp | 16 +-- arbor/memory/copy.hpp | 8 +- arbor/memory/device_coordinator.hpp | 2 +- arbor/memory/fill.hpp | 2 +- arbor/memory/host_coordinator.hpp | 2 +- arbor/memory/wrappers.hpp | 14 +-- arbor/partition_load_balance.cpp | 3 +- arbor/sampler_map.hpp | 7 +- arbor/threading/cthread_impl.hpp | 4 +- arbor/threading/serial.hpp | 2 +- arbor/util/counter.hpp | 2 +- arbor/util/cycle.hpp | 56 +++++---- arbor/util/deduce_return.hpp | 10 -- arbor/util/either.hpp | 10 +- arbor/util/filter.hpp | 88 +++++--------- arbor/util/index_into.hpp | 37 ++---- arbor/util/indirect.hpp | 17 +-- arbor/util/iterutil.hpp | 22 ++-- arbor/util/maputil.hpp | 65 +++++------ arbor/util/meta.hpp | 108 ++++++++---------- arbor/util/partition.hpp | 2 +- arbor/util/partition_iterator.hpp | 4 +- arbor/util/range.hpp | 53 ++++----- arbor/util/rangeutil.hpp | 70 +++++++----- arbor/util/scope_exit.hpp | 8 +- arbor/util/sentinel.hpp | 8 +- arbor/util/span.hpp | 19 +-- arbor/util/transform.hpp | 57 +++++---- aux/tinyopt.hpp | 2 +- example/brunel/brunel_miniapp.cpp | 3 +- example/brunel/io.cpp | 3 +- example/miniapp/io.cpp | 5 +- example/miniapp/miniapp.cpp | 2 +- include/arbor/common_types.hpp | 4 +- include/arbor/constants.hpp | 2 - include/arbor/generic_event.hpp | 10 +- include/arbor/mc_segment.hpp | 7 +- include/arbor/mechinfo.hpp | 16 +-- include/arbor/simd/avx512.hpp | 16 +-- include/arbor/simd/implbase.hpp | 1 + include/arbor/simd/simd.hpp | 24 ++-- include/arbor/simple_sampler.hpp | 2 +- include/arbor/simulation.hpp | 4 +- include/arbor/time_sequence.hpp | 5 +- include/arbor/util/any.hpp | 11 +- include/arbor/util/any_ptr.hpp | 2 +- include/arbor/util/enumhash.hpp | 20 ---- include/arbor/util/make_unique.hpp | 18 --- include/arbor/util/optional.hpp | 10 +- include/arbor/util/uninitialized.hpp | 10 +- include/arbor/util/unique_any.hpp | 6 +- lmorpho/lsys_models.cpp | 4 +- lmorpho/lsystem.cpp | 1 - modcc/functionexpander.cpp | 3 +- modcc/modccutil.hpp | 5 - modcc/module.cpp | 7 +- modcc/printer/infoprinter.cpp | 4 +- modcc/token.hpp | 10 -- .../unit-distributed/distributed_listener.hpp | 3 + test/unit-modcc/test_printers.cpp | 18 ++- test/unit/common.hpp | 9 -- test/unit/test_algorithms.cpp | 2 +- test/unit/test_any.cpp | 9 +- test/unit/test_compartments.cpp | 2 +- test/unit/test_cycle.cpp | 4 +- test/unit/test_fvm_layout.cpp | 13 ++- test/unit/test_fvm_lowered.cpp | 26 ++--- test/unit/test_maputil.cpp | 7 +- test/unit/test_math.cpp | 26 ++--- test/unit/test_mc_cell.cpp | 11 +- test/unit/test_mechcat.cpp | 10 +- test/unit/test_multi_event_stream.cpp | 11 +- test/unit/test_optional.cpp | 12 +- test/unit/test_range.cpp | 44 +++---- test/unit/test_segment.cpp | 5 +- test/unit/test_simd.cpp | 17 +-- test/unit/test_strprintf.cpp | 4 +- test/unit/test_unique_any.cpp | 1 - test/unit/test_vector.cpp | 6 +- test/unit/test_vector.cu | 6 +- test/validation/trace_analysis.hpp | 29 ++--- test/validation/validate_kinetic.cpp | 3 +- test/validation/validate_soma.cpp | 2 +- 95 files changed, 584 insertions(+), 774 deletions(-) delete mode 100644 arbor/util/deduce_return.hpp delete mode 100644 include/arbor/util/enumhash.hpp delete mode 100644 include/arbor/util/make_unique.hpp diff --git a/.travis.yml b/.travis.yml index 3a6abcce..dfb339db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ addons: sources: - ubuntu-toolchain-r-test packages: - - g++-5 + - g++-6 - openmpi-bin - libopenmpi-dev @@ -23,8 +23,8 @@ env: - BUILD_NAME=mpitbb WITH_THREAD=tbb WITH_DISTRIBUTED=mpi before_install: - - CC=gcc-5 - - CXX=g++-5 + - CC=gcc-6 + - CXX=g++-6 script: source ./scripts/travis/build.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ba6d75d..7307476e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -# 3.9 requirement for CUDA language support. -cmake_minimum_required(VERSION 3.9) +# 3.8 requirement for CUDA language support. +cmake_minimum_required(VERSION 3.8) project(arbor VERSION 0.1) enable_language(CXX) @@ -103,7 +103,7 @@ include("CompilerOptions") add_compile_options( "$<$<COMPILE_LANGUAGE:CXX>:${CXXOPT_DEBUG}>" "$<$<COMPILE_LANGUAGE:CXX>:${CXXOPT_WALL}>") -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) #---------------------------------------------------------- # Set up flags and dependencies: diff --git a/arbor/algorithms.hpp b/arbor/algorithms.hpp index 7ae4a5c5..4e295834 100644 --- a/arbor/algorithms.hpp +++ b/arbor/algorithms.hpp @@ -31,7 +31,7 @@ typename util::sequence_traits<C>::value_type sum(C const& c) { using value_type = typename util::sequence_traits<C>::value_type; - return std::accumulate(util::cbegin(c), util::cend(c), value_type{0}); + return std::accumulate(std::cbegin(c), std::cend(c), value_type{0}); } template <typename C> @@ -120,30 +120,14 @@ bool is_minimal_degree(C const& c) return it==c.end(); } -struct generic_is_positive { - template <typename V> - bool operator()(V v) const { - static V zero = V{}; - return v>zero; - } -}; - -struct generic_is_negative { - template <typename V> - bool operator()(V v) const { - static V zero = V{}; - return v<zero; - } -}; - template <typename C> bool all_positive(const C& c) { - return util::all_of(c, generic_is_positive{}); + return util::all_of(c, [](auto v) { return v>decltype(v){}; }); } template <typename C> bool all_negative(const C& c) { - return util::all_of(c, generic_is_negative{}); + return util::all_of(c, [](auto v) { return v<decltype(v){}; }); } template<typename C> @@ -311,7 +295,10 @@ std::vector<typename C::value_type> tree_reduce( template <typename Seq, typename = util::enable_if_sequence_t<Seq&>> bool is_unique(const Seq& seq) { - return std::adjacent_find(std::begin(seq), std::end(seq)) == std::end(seq); + using std::begin; + using std::end; + + return std::adjacent_find(begin(seq), end(seq)) == end(seq); } @@ -319,7 +306,6 @@ bool is_unique(const Seq& seq) { /// about where a match was found. // TODO: consolidate these with rangeutil routines; make them sentinel -// friendly; use ADL for begin/end (simpler with C++14). template <typename It, typename T> It binary_find(It b, It e, const T& value) { @@ -328,17 +314,19 @@ It binary_find(It b, It e, const T& value) { } template <typename Seq, typename T> -auto binary_find(const Seq& seq, const T& value) - -> decltype(binary_find(std::begin(seq), std::end(seq), value)) -{ - return binary_find(std::begin(seq), std::end(seq), value); +auto binary_find(const Seq& seq, const T& value) { + using std::begin; + using std::end; + + return binary_find(begin(seq), end(seq), value); } template <typename Seq, typename T> -auto binary_find(Seq& seq, const T& value) - -> decltype(binary_find(std::begin(seq), std::end(seq), value)) -{ - return binary_find(std::begin(seq), std::end(seq), value); +auto binary_find(Seq& seq, const T& value) { + using std::begin; + using std::end; + + return binary_find(begin(seq), end(seq), value); } } // namespace algorithms diff --git a/arbor/backends/builtin_mech_proto.hpp b/arbor/backends/builtin_mech_proto.hpp index 1fcb292c..892f122f 100644 --- a/arbor/backends/builtin_mech_proto.hpp +++ b/arbor/backends/builtin_mech_proto.hpp @@ -14,9 +14,9 @@ inline const mechanism_info& builtin_stimulus_info() { {}, // parameters { - {"delay", spec(spec::parameter, "ms", 0, 0)}, - {"duration", spec(spec::parameter, "ms", 0, 0)}, - {"amplitude", spec(spec::parameter, "nA", 0, 0)} + {"delay", {spec::parameter, "ms", 0, 0}}, + {"duration", {spec::parameter, "ms", 0, 0}}, + {"amplitude", {spec::parameter, "nA", 0, 0}} }, // state {}, diff --git a/arbor/backends/gpu/shared_state.hpp b/arbor/backends/gpu/shared_state.hpp index 6193fc39..da1ae4ef 100644 --- a/arbor/backends/gpu/shared_state.hpp +++ b/arbor/backends/gpu/shared_state.hpp @@ -7,7 +7,6 @@ #include <arbor/fvm_types.hpp> #include <arbor/ion.hpp> -#include <arbor/util/enumhash.hpp> #include "backends/gpu/gpu_store_types.hpp" @@ -77,7 +76,7 @@ struct shared_state { array voltage; // Maps CV index to membrane voltage [mV]. array current_density; // Maps CV index to current density [A/m²]. - std::unordered_map<ionKind, ion_state, util::enum_hash> ion_data; + std::unordered_map<ionKind, ion_state> ion_data; deliverable_event_stream deliverable_events; diff --git a/arbor/backends/multicore/shared_state.hpp b/arbor/backends/multicore/shared_state.hpp index af2b19be..294f4534 100644 --- a/arbor/backends/multicore/shared_state.hpp +++ b/arbor/backends/multicore/shared_state.hpp @@ -12,7 +12,6 @@ #include <arbor/fvm_types.hpp> #include <arbor/ion.hpp> #include <arbor/simd/simd.hpp> -#include <arbor/util/enumhash.hpp> #include "backends/event.hpp" #include "event_queue.hpp" @@ -96,7 +95,7 @@ struct shared_state { array voltage; // Maps CV index to membrane voltage [mV]. array current_density; // Maps CV index to current density [A/m²]. - std::unordered_map<ionKind, ion_state, util::enum_hash> ion_data; + std::unordered_map<ionKind, ion_state> ion_data; deliverable_event_stream deliverable_events; diff --git a/arbor/fvm_layout.cpp b/arbor/fvm_layout.cpp index 6f3d1ee9..0f75ffe2 100644 --- a/arbor/fvm_layout.cpp +++ b/arbor/fvm_layout.cpp @@ -5,7 +5,6 @@ #include <arbor/arbexcept.hpp> #include <arbor/mc_cell.hpp> -#include <arbor/util/enumhash.hpp> #include "algorithms.hpp" #include "fvm_compartment.hpp" @@ -302,7 +301,7 @@ fvm_mechanism_data fvm_build_mechanism_data(const mechanism_catalogue& catalogue // Temporary table for presence of ion channels, mapping ionKind to _sorted_ // collection of segment indices. - std::unordered_map<ionKind, std::set<size_type>, util::enum_hash> ion_segments; + std::unordered_map<ionKind, std::set<size_type>> ion_segments; auto update_paramset_and_validate = [&catalogue] @@ -441,10 +440,14 @@ fvm_mechanism_data fvm_build_mechanism_data(const mechanism_catalogue& catalogue std::vector<std::vector<value_type>> param_value(nparam); std::vector<std::vector<value_type>> param_area_contrib(nparam); - const auto& info = *entry.second.info; // TODO: C++14, use lambda capture with initializer - auto& ion_configs = mechdata.ions; // TODO: C++14 ditto + // (gcc 6.x bug fails to deduce const in lambda capture reference initialization) + const auto& info = *entry.second.info; auto accumulate_mech_data = - [¶m_index, ¶m_value, ¶m_area_contrib, &config, &info, &ion_configs] + [ + &info, + &ion_configs = mechdata.ions, + ¶m_index, ¶m_value, ¶m_area_contrib, &config + ] (size_type index, index_type cv, value_type area, const mechanism_desc& desc) { for (auto& kv: desc.values()) { diff --git a/arbor/fvm_layout.hpp b/arbor/fvm_layout.hpp index 9d09e5ca..ceeb3008 100644 --- a/arbor/fvm_layout.hpp +++ b/arbor/fvm_layout.hpp @@ -5,10 +5,8 @@ #include <arbor/mechanism.hpp> #include <arbor/mechinfo.hpp> #include <arbor/mechcat.hpp> -#include <arbor/util/enumhash.hpp> #include "fvm_compartment.hpp" -#include "util/deduce_return.hpp" #include "util/span.hpp" namespace arb { @@ -71,11 +69,13 @@ struct fvm_discretization { std::vector<size_type> cell_segment_bounds; // Partitions segment indices by cell. std::vector<index_type> cell_cv_bounds; // Partitions CV indices by cell. - auto cell_segment_part() const - DEDUCED_RETURN_TYPE(util::partition_view(cell_segment_bounds)) + auto cell_segment_part() const { + return util::partition_view(cell_segment_bounds); + } - auto cell_cv_part() const - DEDUCED_RETURN_TYPE(util::partition_view(cell_cv_bounds)) + auto cell_cv_part() const { + return util::partition_view(cell_cv_bounds); + } size_type segment_location_cv(size_type cell_index, segment_location segloc) const { auto cell_segs = cell_segment_part()[cell_index]; @@ -130,7 +130,7 @@ struct fvm_mechanism_data { std::unordered_map<std::string, fvm_mechanism_config> mechanisms; // Ion config, indexed by ionKind. - std::unordered_map<ionKind, fvm_ion_config, util::enum_hash> ions; + std::unordered_map<ionKind, fvm_ion_config> ions; // Total number of targets (point-mechanism points) std::size_t ntarget = 0; diff --git a/arbor/fvm_lowered_cell_impl.hpp b/arbor/fvm_lowered_cell_impl.hpp index b07fcfea..82ecbba6 100644 --- a/arbor/fvm_lowered_cell_impl.hpp +++ b/arbor/fvm_lowered_cell_impl.hpp @@ -9,9 +9,10 @@ #include <cmath> #include <iterator> +#include <memory> +#include <stdexcept> #include <utility> #include <vector> -#include <stdexcept> #include <arbor/assert.hpp> #include <arbor/common_types.hpp> @@ -351,7 +352,7 @@ void fvm_lowered_cell_impl<B>::initialize( util::transform_view(keys(mech_data.mechanisms), [&](const std::string& name) { return mech_instance(name)->data_alignment(); })); - state_ = util::make_unique<shared_state>(ncell, D.cv_to_cell, data_alignment? data_alignment: 1u); + state_ = std::make_unique<shared_state>(ncell, D.cv_to_cell, data_alignment? data_alignment: 1u); // Instantiate mechanisms and ions. diff --git a/arbor/math.hpp b/arbor/math.hpp index 4db898af..6f538cf0 100644 --- a/arbor/math.hpp +++ b/arbor/math.hpp @@ -8,26 +8,11 @@ namespace arb { namespace math { -// TODO: C++14 variable template template <typename T> -T constexpr pi() { - return T(3.1415926535897932384626433832795l); -} +T constexpr pi = 3.1415926535897932384626433832795l; template <typename T = float> -T constexpr infinity() { - return std::numeric_limits<T>::infinity(); -} - -template <typename T> -T constexpr mean(T a, T b) { - return (a+b) / T(2); -} - -template <typename T> -T constexpr mean(std::pair<T,T> const& p) { - return (p.first+p.second) / T(2); -} +T constexpr infinity = std::numeric_limits<T>::infinity(); template <typename T> T constexpr square(T a) { @@ -42,32 +27,32 @@ T constexpr cube(T a) { // Area of circle radius r. template <typename T> T constexpr area_circle(T r) { - return pi<T>() * square(r); + return pi<T> * square(r); } // Surface area of conic frustrum excluding the discs at each end, // with length L, end radii r1, r2. template <typename T> T constexpr area_frustrum(T L, T r1, T r2) { - return pi<T>() * (r1+r2) * sqrt(square(L) + square(r1-r2)); + return pi<T> * (r1+r2) * sqrt(square(L) + square(r1-r2)); } // Volume of conic frustrum of length L, end radii r1, r2. template <typename T> T constexpr volume_frustrum(T L, T r1, T r2) { - return pi<T>()/T(3) * (square(r1+r2) - r1*r2) * L; + return pi<T>/T(3) * (square(r1+r2) - r1*r2) * L; } // Volume of a sphere radius r. template <typename T> T constexpr volume_sphere(T r) { - return T(4)/T(3) * pi<T>() * cube(r); + return T(4)/T(3) * pi<T> * cube(r); } // Surface area of a sphere radius r. template <typename T> T constexpr area_sphere(T r) { - return T(4) * pi<T>() * square(r); + return T(4) * pi<T> * square(r); } // Linear interpolation by u in interval [a,b]: (1-u)*a + u*b. @@ -87,7 +72,7 @@ int signum(T x) { // next_pow2(x) returns 0 if x==0, else returns smallest 2^k such // that 2^k>=x. -template <typename U, typename = typename std::enable_if<std::is_unsigned<U>::value>::type> +template <typename U, typename = std::enable_if_t<std::is_unsigned<U>::value>> U next_pow2(U x) { --x; for (unsigned s=1; s<std::numeric_limits<U>::digits; s<<=1) { @@ -121,8 +106,8 @@ namespace impl { template < typename T, typename U, - typename C = typename std::common_type<T, U>::type, - typename Signed = typename std::is_signed<C>::type + typename C = std::common_type_t<T, U>, + typename Signed = std::is_signed<C> > C round_up(T v, U b) { C m = v%b; diff --git a/arbor/mechcat.cpp b/arbor/mechcat.cpp index ed314a78..26d21b93 100644 --- a/arbor/mechcat.cpp +++ b/arbor/mechcat.cpp @@ -5,14 +5,13 @@ #include <arbor/arbexcept.hpp> #include <arbor/mechcat.hpp> -#include <arbor/util/make_unique.hpp> #include "util/maputil.hpp" namespace arb { using util::value_by_key; -using util::make_unique; +using std::make_unique; void mechanism_catalogue::add(const std::string& name, mechanism_info info) { if (has(name)) { @@ -133,20 +132,17 @@ std::unique_ptr<mechanism> mechanism_catalogue::instance_impl(std::type_index ti } std::unique_ptr<mechanism> mech = prototype->clone(); - // TODO: make recursive lambda without std::function in C++14 - std::function<void (std::string, mechanism*)> apply_globals = - [this, &apply_globals](const std::string& name, mechanism* mptr) - { + + auto apply_globals = [this](auto& self, const std::string& name, mechanism* mptr) -> void { if (auto p = value_by_key(derived_map_, name)) { - apply_globals(p->parent, mptr); + self(self, p->parent, mptr); for (auto& kv: p->globals) { mptr->set_global(kv.first, kv.second); } } }; - - apply_globals(name, mech.get()); + apply_globals(apply_globals, name, mech.get()); return mech; } diff --git a/arbor/memory/array.hpp b/arbor/memory/array.hpp index e2915e6f..59fd4c39 100644 --- a/arbor/memory/array.hpp +++ b/arbor/memory/array.hpp @@ -68,8 +68,8 @@ namespace impl { template <typename T> struct is_array : std::conditional< - impl::is_array_by_value<typename std::decay<T>::type>::value || - impl::is_array_view <typename std::decay<T>::type>::value, + impl::is_array_by_value<std::decay_t<T>>::value || + impl::is_array_view <std::decay_t<T>>::value, std::true_type, std::false_type >::type {}; @@ -116,7 +116,7 @@ public: // constructor by size template < typename I, - typename = typename std::enable_if<std::is_integral<I>::value>::type> + typename = std::enable_if_t<std::is_integral<I>::value>> array(I n) : base(coordinator_type().allocate(n)) { @@ -129,8 +129,8 @@ public: // constructor by size with default value template < typename II, typename TT, - typename = typename std::enable_if<std::is_integral<II>::value>::type, - typename = typename std::enable_if<std::is_convertible<TT,value_type>::value>::type > + typename = std::enable_if_t<std::is_integral<II>::value>, + typename = std::enable_if_t<std::is_convertible<TT,value_type>::value> > array(II n, TT value) : base(coordinator_type().allocate(n)) { @@ -168,7 +168,7 @@ public: // copy constructor where other is an array, array_view or array_reference template < typename Other, - typename = typename std::enable_if<impl::is_array_t<Other>::value>::type + typename = std::enable_if_t<impl::is_array_t<Other>::value> > array(const Other& other) : base(coordinator_type().allocate(other.size())) @@ -216,7 +216,7 @@ public: template < typename It, - typename = arb::util::enable_if_t<arb::util::is_random_access_iterator<It>::value> > + typename = std::enable_if_t<arb::util::is_random_access_iterator<It>::value> > array(It b, It e) : base(coordinator_type().allocate(std::distance(b, e))) { diff --git a/arbor/memory/array_view.hpp b/arbor/memory/array_view.hpp index 3c187761..f63ccb29 100644 --- a/arbor/memory/array_view.hpp +++ b/arbor/memory/array_view.hpp @@ -138,7 +138,7 @@ public: // Constructors template < typename Other, - typename = typename std::enable_if< impl::is_array<Other>::value >::type + typename = std::enable_if_t< impl::is_array<Other>::value > > explicit array_view(Other&& other) : pointer_(other.data()), size_(other.size()) @@ -146,7 +146,7 @@ public: #ifdef VERBOSE std::cout << util::green("array_view(&&Other) ") << "\n this " << util::pretty_printer<array_view>::print(*this) - << "\n other " << util::pretty_printer<typename std::decay<Other>::type>::print(other) + << "\n other " << util::pretty_printer<std::decay_t<Other>>::print(other) << "\n"; #endif } @@ -210,7 +210,7 @@ public: template < typename Other, - typename = typename std::enable_if< impl::is_array<Other>::value >::type + typename = std::enable_if_t< impl::is_array<Other>::value > > array_view operator=(Other&& other) { #if VERBOSE @@ -286,7 +286,7 @@ public: } static constexpr auto - alignment() -> decltype(coordinator_type::alignment()) { + alignment() { return coordinator_type::alignment(); } @@ -342,7 +342,7 @@ public: // Constructors template < typename Other, - typename = typename std::enable_if< impl::is_array<Other>::value >::type + typename = std::enable_if_t< impl::is_array<Other>::value > > const_array_view(const Other& other) : pointer_(other.data()), size_(other.size()) @@ -350,7 +350,7 @@ public: #if VERBOSE std::cout << util::green("const_array_view(const Other&)") << "\n this " << util::pretty_printer<const_array_view>::print(*this) - << "\n other " << util::pretty_printer<typename std::decay<Other>::type>::print(other) + << "\n other " << util::pretty_printer<std::decay_t<Other>>::print(other) << std::endl; #endif } @@ -401,7 +401,7 @@ public: template < typename Other, - typename = typename std::enable_if< impl::is_array<Other>::value >::type + typename = std::enable_if_t< impl::is_array<Other>::value > > const_array_view operator=(Other&& other) { #if VERBOSE @@ -458,7 +458,7 @@ public: } static constexpr auto - alignment() -> decltype(coordinator_type::alignment()) { + alignment() { return coordinator_type::alignment(); } diff --git a/arbor/memory/copy.hpp b/arbor/memory/copy.hpp index 9d864376..87f7495b 100644 --- a/arbor/memory/copy.hpp +++ b/arbor/memory/copy.hpp @@ -17,9 +17,9 @@ void copy(LHS&& from, RHS&& to) { #ifdef VERBOSE std::cerr << util::blue("copy") << " " - << util::pretty_printer<typename std::decay<LHS>::type>::print(from) + << util::pretty_printer<std::decay_t<LHS>>::print(from) << util::cyan(" -> ") - << util::pretty_printer<typename std::decay<RHS>::type>::print(to) << "\n"; + << util::pretty_printer<std::decay_t<RHS>>::print(to) << "\n"; #endif // adapt views to the inputs auto lhs = make_const_view(from); @@ -33,7 +33,7 @@ void copy(LHS&& from, RHS&& to) { template <typename LHS, typename T> void fill(LHS&& target, T value) { - using lhs_type = typename std::decay<LHS>::type; + using lhs_type = std::decay_t<LHS>; static_assert( std::is_convertible<T, typename lhs_type::value_type>::value, "can't fill container with a value of the supplied type" @@ -41,7 +41,7 @@ void fill(LHS&& target, T value) { #ifdef VERBOSE std::cerr << util::blue("fill") << " " - << util::pretty_printer<typename std::decay<LHS>::type>::print(target) + << util::pretty_printer<std::decay_t<LHS>>::print(target) << util::cyan(" <- ") << T(value) << "\n"; #endif diff --git a/arbor/memory/device_coordinator.hpp b/arbor/memory/device_coordinator.hpp index 812684f4..d886a0be 100644 --- a/arbor/memory/device_coordinator.hpp +++ b/arbor/memory/device_coordinator.hpp @@ -236,7 +236,7 @@ public: } static constexpr - auto alignment() -> decltype(Allocator_::alignment()) { + auto alignment() { return Allocator_::alignment(); } diff --git a/arbor/memory/fill.hpp b/arbor/memory/fill.hpp index c118c139..11d0da59 100644 --- a/arbor/memory/fill.hpp +++ b/arbor/memory/fill.hpp @@ -33,7 +33,7 @@ void fill64(uint64_t* v, uint64_t value, std::size_t n); #define FILL(N) \ template <typename T> \ -typename std::enable_if<sizeof(T)==sizeof(uint ## N ## _t)>::type \ +std::enable_if_t<sizeof(T)==sizeof(uint ## N ## _t)> \ fill(T* ptr, T value, std::size_t n) { \ using I = uint ## N ## _t; \ I v; \ diff --git a/arbor/memory/host_coordinator.hpp b/arbor/memory/host_coordinator.hpp index 19f770df..0f814cdb 100644 --- a/arbor/memory/host_coordinator.hpp +++ b/arbor/memory/host_coordinator.hpp @@ -177,7 +177,7 @@ public: } static constexpr auto - alignment() -> decltype(Allocator::alignment()) { + alignment() { return Allocator::alignment(); } diff --git a/arbor/memory/wrappers.hpp b/arbor/memory/wrappers.hpp index f51daa03..6f3d6532 100644 --- a/arbor/memory/wrappers.hpp +++ b/arbor/memory/wrappers.hpp @@ -87,7 +87,7 @@ namespace util { template <typename T> constexpr bool is_on_host_v() { - return is_on_host<typename std::decay<T>::type>::value; + return is_on_host<std::decay_t<T>>::value; } template <typename T> @@ -104,7 +104,7 @@ namespace util { template <typename T> constexpr bool is_on_gpu_v() { - return is_on_gpu<typename std::decay<T>::type>::value; + return is_on_gpu<std::decay_t<T>>::value; } } @@ -118,15 +118,15 @@ namespace util { // host template < typename C, - typename = typename std::enable_if<util::is_on_host_v<C>()>::type + typename = std::enable_if_t<util::is_on_host_v<C>()> > -auto on_host(const C& c) -> decltype(make_const_view(c)) { +auto on_host(const C& c) { return make_const_view(c); } template < typename C, - typename = typename std::enable_if<util::is_on_gpu_v<C>()>::type + typename = std::enable_if_t<util::is_on_gpu_v<C>()> > auto on_host(const C& c) -> host_vector<typename C::value_type> { using T = typename C::value_type; @@ -136,7 +136,7 @@ auto on_host(const C& c) -> host_vector<typename C::value_type> { // gpu template < typename C, - typename = typename std::enable_if<util::is_on_gpu_v<C>()>::type + typename = std::enable_if_t<util::is_on_gpu_v<C>()> > auto on_gpu(const C& c) -> decltype(make_const_view(c)) { return make_const_view(c); @@ -144,7 +144,7 @@ auto on_gpu(const C& c) -> decltype(make_const_view(c)) { template < typename C, - typename = typename std::enable_if<util::is_on_host_v<C>()>::type + typename = std::enable_if_t<util::is_on_host_v<C>()> > auto on_gpu(const C& c) -> device_vector<typename C::value_type> { using T = typename C::value_type; diff --git a/arbor/partition_load_balance.cpp b/arbor/partition_load_balance.cpp index c9a18ec2..472c61ef 100644 --- a/arbor/partition_load_balance.cpp +++ b/arbor/partition_load_balance.cpp @@ -1,5 +1,4 @@ #include <arbor/distributed_context.hpp> -#include <arbor/util/enumhash.hpp> #include <arbor/domain_decomposition.hpp> #include <arbor/recipe.hpp> @@ -46,7 +45,7 @@ domain_decomposition partition_load_balance(const recipe& rec, // Local load balance - std::unordered_map<cell_kind, std::vector<cell_gid_type>, arb::util::enum_hash> + std::unordered_map<cell_kind, std::vector<cell_gid_type>> kind_lists; for (auto gid: make_span(gid_part[domain_id])) { kind_lists[rec.get_cell_kind(gid)].push_back(gid); diff --git a/arbor/sampler_map.hpp b/arbor/sampler_map.hpp index 5d137fbf..e99d6b4a 100644 --- a/arbor/sampler_map.hpp +++ b/arbor/sampler_map.hpp @@ -13,7 +13,6 @@ #include <arbor/sampling.hpp> #include <arbor/schedule.hpp> -#include "util/deduce_return.hpp" #include "util/transform.hpp" namespace arb { @@ -52,13 +51,13 @@ private: std::mutex m_; static sampler_association& second(assoc_map::value_type& p) { return p.second; } - auto assoc_view() DEDUCED_RETURN_TYPE((util::transform_view(map_, &sampler_association_map::second))) + auto assoc_view() { return util::transform_view(map_, &sampler_association_map::second); } public: // Range-like view presents just the associations, omitting the handles. - auto begin() DEDUCED_RETURN_TYPE(assoc_view().begin()); - auto end() DEDUCED_RETURN_TYPE(assoc_view().end()); + auto begin() { return assoc_view().begin(); } + auto end() { return assoc_view().end(); } }; // Manage associations between probe ids, probe tags, and (lowered cell) probe handles. diff --git a/arbor/threading/cthread_impl.hpp b/arbor/threading/cthread_impl.hpp index 52e84be0..8d0fe219 100644 --- a/arbor/threading/cthread_impl.hpp +++ b/arbor/threading/cthread_impl.hpp @@ -140,7 +140,7 @@ public : return data[global_task_pool.get_current_thread()]; } - auto size() -> decltype(data.size()) const { return data.size(); } + auto size() const { return data.size(); } iterator begin() { return data.begin(); } iterator end() { return data.end(); } @@ -163,7 +163,7 @@ private: // call a function of type X f() in a lock template<typename F> - auto critical(F f) -> decltype(f()) { + decltype(auto) critical(F f) { impl::lock lock{mutex}; return f(); } diff --git a/arbor/threading/serial.hpp b/arbor/threading/serial.hpp index 103818f6..af3b0594 100644 --- a/arbor/threading/serial.hpp +++ b/arbor/threading/serial.hpp @@ -34,7 +34,7 @@ public : T& local() { return data[0]; } const T& local() const { return data[0]; } - auto size() -> decltype(data.size()) const { return data.size(); } + auto size() const { return data.size(); } iterator begin() { return data.begin(); } iterator end() { return data.end(); } diff --git a/arbor/util/counter.hpp b/arbor/util/counter.hpp index 4328876d..fc59c4a4 100644 --- a/arbor/util/counter.hpp +++ b/arbor/util/counter.hpp @@ -9,7 +9,7 @@ namespace arb { namespace util { -template <typename V, typename = typename std::enable_if<std::is_integral<V>::value>::type> +template <typename V, typename = std::enable_if_t<std::is_integral<V>::value>> struct counter { using difference_type = V; using value_type = V; diff --git a/arbor/util/cycle.hpp b/arbor/util/cycle.hpp index 83fe7e08..5664be0a 100644 --- a/arbor/util/cycle.hpp +++ b/arbor/util/cycle.hpp @@ -1,9 +1,11 @@ #pragma once #include <initializer_list> +#include <type_traits> #include <utility> -#include <util/iterutil.hpp> -#include <util/range.hpp> + +#include "util/iterutil.hpp" +#include "util/range.hpp" namespace arb { namespace util { @@ -183,35 +185,39 @@ cyclic_iterator<I, S> make_cyclic_iterator(const I& iter, const S& sentinel) { } -template < - typename Seq, - typename SeqIter = typename sequence_traits<Seq>::const_iterator, - typename SeqSentinel = typename sequence_traits<Seq>::const_sentinel, - typename = enable_if_t<std::is_same<SeqIter, SeqSentinel>::value> -> -range<cyclic_iterator<SeqIter, SeqSentinel> > cyclic_view(const Seq& s) { - return { make_cyclic_iterator(util::cbegin(s), util::cend(s)), - make_cyclic_iterator(util::cend(s), util::cend(s)) }; +// TODO C++17: simplify with constexpr-if +namespace cycle_impl { + using std::begin; + using std::end; + + // cycle over regular sequences: + template <typename Seq> + auto cycle_(Seq&& s, std::true_type) { + auto b = begin(s); + auto e = end(s); + return make_range(make_cyclic_iterator(b, e), make_cyclic_iterator(e, e)); + } + + // cycle over sentinel-terminated sequences: + template <typename Seq> + auto cycle_(Seq&& s, std::false_type) { + auto b = begin(s); + auto e = end(s); + return make_range(make_cyclic_iterator(b, e), e); + } } -template < - typename Seq, - typename SeqIter = typename sequence_traits<Seq>::const_iterator, - typename SeqSentinel = typename sequence_traits<Seq>::const_sentinel, - typename = enable_if_t<!std::is_same<SeqIter, SeqSentinel>::value> -> -range<cyclic_iterator<SeqIter, SeqSentinel>, SeqSentinel> -cyclic_view(const Seq& s) { - return { make_cyclic_iterator(util::cbegin(s), util::cend(s)), util::cend(s) }; +template <typename Seq> +auto cyclic_view(Seq&& s) { + return cycle_impl::cycle_(std::forward<Seq>(s), is_regular_sequence<Seq&&>{}); } // Handle initializer lists template <typename T> -range<cyclic_iterator<typename std::initializer_list<T>::const_iterator, - typename std::initializer_list<T>::const_iterator> > -cyclic_view(const std::initializer_list<T> &list) { - return { make_cyclic_iterator(util::cbegin(list), util::cend(list)), - make_cyclic_iterator(util::cend(list), util::cend(list)) }; +auto cyclic_view(const std::initializer_list<T>& list) { + return make_range( + make_cyclic_iterator(list.begin(), list.end()), + make_cyclic_iterator(list.end(), list.end())); } } // namespace util diff --git a/arbor/util/deduce_return.hpp b/arbor/util/deduce_return.hpp deleted file mode 100644 index 1211ebfb..00000000 --- a/arbor/util/deduce_return.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -/* Just one macro, to fill the gap before C++14 */ - -#ifdef DEDUCED_RETURN_TYPE -#undef DEDUCED_RETURN_TYPE -#endif - -#define DEDUCED_RETURN_TYPE(expr) -> decltype(expr) { return expr; } - diff --git a/arbor/util/either.hpp b/arbor/util/either.hpp index 8b40b735..faea135a 100644 --- a/arbor/util/either.hpp +++ b/arbor/util/either.hpp @@ -116,7 +116,7 @@ public: typename A_ = A, bool a_ = std::is_default_constructible<A_>::value, bool b_ = std::is_default_constructible<B>::value, - typename = enable_if_t<a_ || (!a_ && b_)>, + typename = std::enable_if_t<a_ || (!a_ && b_)>, std::size_t w_ = a_? 0: 1 > either() noexcept(std::is_nothrow_default_constructible<typename getter<w_>::type>::value): @@ -132,7 +132,7 @@ public: template < typename B_ = B, - typename = enable_if_t<!std::is_same<A, B_>::value> + typename = std::enable_if_t<!std::is_same<A, B_>::value> > either(const B& b) noexcept(std::is_nothrow_copy_constructible<B>::value): which(1) { getter<1>::field(*this).construct(b); @@ -144,7 +144,7 @@ public: template < typename B_ = B, - typename = enable_if_t<!std::is_same<A, B_>::value> + typename = std::enable_if_t<!std::is_same<A, B_>::value> > either(B&& b) noexcept(std::is_nothrow_move_constructible<B>::value): which(1) { getter<1>::field(*this).construct(std::move(b)); @@ -309,12 +309,12 @@ public: // pointer to element access: return nullptr if it does not hold this item template <std::size_t I> - auto ptr() -> decltype(getter<I>::ptr(which, *this)) { + auto ptr() { return getter<I>::ptr(which, *this); } template <std::size_t I> - auto ptr() const -> decltype(getter<I>::ptr(which, *this)) { + auto ptr() const { return getter<I>::ptr(which, *this); } diff --git a/arbor/util/filter.hpp b/arbor/util/filter.hpp index c8ff4419..43f6fd88 100644 --- a/arbor/util/filter.hpp +++ b/arbor/util/filter.hpp @@ -69,11 +69,12 @@ class filter_iterator { public: using value_type = typename std::iterator_traits<I>::value_type; using difference_type = typename std::iterator_traits<I>::difference_type; - using iterator_category = typename std::conditional< - is_forward_iterator<I>::value, - std::forward_iterator_tag, - std::input_iterator_tag - >::type; + using iterator_category = + std::conditional_t< + is_forward_iterator<I>::value, + std::forward_iterator_tag, + std::input_iterator_tag + >; using pointer = typename std::iterator_traits<I>::pointer; using reference = typename std::iterator_traits<I>::reference; @@ -129,7 +130,7 @@ public: // forward and input iterator requirements - auto operator*() const -> decltype(*(this->inner_)) { + decltype(auto) operator*() const { advance(); return *inner_; } @@ -182,62 +183,35 @@ public: }; template <typename I, typename S, typename F> -filter_iterator<I, S, util::decay_t<F>> make_filter_iterator(const I& i, const S& end, const F& f) { - return filter_iterator<I, S, util::decay_t<F>>(i, end, f); +filter_iterator<I, S, std::decay_t<F>> make_filter_iterator(const I& i, const S& end, const F& f) { + return filter_iterator<I, S, std::decay_t<F>>(i, end, f); } -// filter over const and non-const regular sequences: - -template < - typename Seq, - typename F, - typename seq_iter = typename sequence_traits<Seq>::iterator, - typename seq_sent = typename sequence_traits<Seq>::sentinel, - typename = enable_if_t<std::is_same<seq_iter, seq_sent>::value> -> -range<filter_iterator<seq_iter, seq_iter, util::decay_t<F>>> -filter(Seq& s, const F& f) { - return {make_filter_iterator(std::begin(s), std::end(s), f), - make_filter_iterator(std::end(s), std::end(s), f)}; -} - -template < - typename Seq, - typename F, - typename seq_citer = typename sequence_traits<Seq>::const_iterator, - typename seq_csent = typename sequence_traits<Seq>::const_sentinel, - typename = enable_if_t<std::is_same<seq_citer, seq_csent>::value> -> -range<filter_iterator<seq_citer, seq_citer, util::decay_t<F>>> -filter(const Seq& s, const F& f) { - return {make_filter_iterator(util::cbegin(s), util::cend(s), f), - make_filter_iterator(util::cend(s), util::cend(s), f)}; -} +// TODO C++17: simplify with constexpr-if +namespace filter_impl { + using std::begin; + using std::end; + + // filter over regular sequences: + template <typename Seq, typename F> + auto filter_(Seq&& s, const F& f, std::true_type) { + auto b = begin(s); + auto e = end(s); + return make_range(make_filter_iterator(b, e, f), make_filter_iterator(e, e, f)); + } -// filter over const and non-const sentinel-terminated sequences: - -template < - typename Seq, - typename F, - typename seq_iter = typename sequence_traits<Seq>::iterator, - typename seq_sent = typename sequence_traits<Seq>::sentinel, - typename = enable_if_t<!std::is_same<seq_iter, seq_sent>::value> -> -range<filter_iterator<seq_iter, seq_sent, util::decay_t<F>>, seq_sent> -filter(Seq& s, const F& f) { - return {make_filter_iterator(std::begin(s), std::end(s), f), std::end(s)}; + // filter over sentinel-terminated sequences: + template <typename Seq, typename F> + auto filter_(Seq&& s, const F& f, std::false_type) { + auto b = begin(s); + auto e = end(s); + return make_range(make_filter_iterator(b, e, f), e); + } } -template < - typename Seq, - typename F, - typename seq_citer = typename sequence_traits<Seq>::const_iterator, - typename seq_csent = typename sequence_traits<Seq>::const_sentinel, - typename = enable_if_t<!std::is_same<seq_citer, seq_csent>::value> -> -range<filter_iterator<seq_citer, seq_csent, util::decay_t<F>>, seq_csent> -filter(const Seq& s, const F& f) { - return {make_filter_iterator(util::cbegin(s), util::cend(s), f), util::cend(s)}; +template <typename Seq, typename F> +auto filter(Seq&& s, const F& f) { + return filter_impl::filter_(std::forward<Seq>(s), f, is_regular_sequence<Seq&&>{}); } } // namespace util diff --git a/arbor/util/index_into.hpp b/arbor/util/index_into.hpp index 879c3bac..c78e706b 100644 --- a/arbor/util/index_into.hpp +++ b/arbor/util/index_into.hpp @@ -30,14 +30,14 @@ struct index_into_iterator { using difference_type = value_type; using pointer = const value_type*; using reference = const value_type&; - using iterator_category = typename - std::conditional< + using iterator_category = + std::conditional_t< std::is_same<Sup, SupEnd>::value && is_bidirectional_iterator_t<Sup>::value && is_bidirectional_iterator_t<Sub>::value, std::bidirectional_iterator_tag, std::forward_iterator_tag - >::type; + >; index_into_iterator(const Sub& sub, const Sub& sub_end, const Sup& sup, const SupEnd& sup_end): sub(sub), sub_end(sub_end), sup(sup), sup_end(sup_end), idx(0) @@ -120,35 +120,18 @@ private: } }; -template < - typename Sub, - typename Super, - typename Canon = decltype(canonical_view(std::declval<Sub>())) -> -auto index_into(const Sub& sub, const Super& sup) - -> range< - index_into_iterator< - typename sequence_traits<Canon>::const_iterator, - typename sequence_traits<Super>::const_iterator, - typename sequence_traits<Super>::const_sentinel - > - > -{ - using iterator = - index_into_iterator< - typename sequence_traits<Canon>::const_iterator, - typename sequence_traits<Super>::const_iterator, - typename sequence_traits<Super>::const_sentinel - >; - +template <typename Sub, typename Super> +auto index_into(const Sub& sub, const Super& sup) { using std::begin; using std::end; auto canon = canonical_view(sub); - iterator b(canon.begin(), canon.end(), begin(sup), end(sup)); - iterator e(canon.end(), canon.end(), begin(sup), end(sup)); + using iterator = index_into_iterator<decltype(canon.begin()), decltype(begin(sup)), decltype(end(sup))>; - return range<iterator>(b, e); + return make_range( + iterator(canon.begin(), canon.end(), begin(sup), end(sup)), + iterator(canon.end(), canon.end(), begin(sup), end(sup)) + ); } } // namespace util diff --git a/arbor/util/indirect.hpp b/arbor/util/indirect.hpp index 0205a15a..301172b2 100644 --- a/arbor/util/indirect.hpp +++ b/arbor/util/indirect.hpp @@ -10,9 +10,8 @@ #include <utility> -#include <util/deduce_return.hpp> -#include <util/transform.hpp> -#include <util/meta.hpp> +#include "util/transform.hpp" +#include "util/meta.hpp" namespace arb { namespace util { @@ -34,14 +33,16 @@ 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))); +auto indirect_view(RASeq& data, const Seq& index_map) { + return transform_view(index_map, impl::indirect_accessor<RASeq&>(data)); +} // icpc 17 fails to disambiguate without further qualification, so // we replace `template <typename RASeq, typename Seq>` with the following: -template <typename RASeq, typename Seq, typename = util::enable_if_t<!std::is_reference<RASeq>::value>> -auto indirect_view(RASeq&& data, const Seq& index_map) -DEDUCED_RETURN_TYPE(transform_view(index_map, impl::indirect_accessor<RASeq>(std::move(data)))); +template <typename RASeq, typename Seq, typename = std::enable_if_t<!std::is_reference<RASeq>::value>> +auto indirect_view(RASeq&& data, const Seq& index_map) { + return transform_view(index_map, impl::indirect_accessor<RASeq>(std::move(data))); +} } // namespace util } // namespace arb diff --git a/arbor/util/iterutil.hpp b/arbor/util/iterutil.hpp index 53b68eec..90a376ee 100644 --- a/arbor/util/iterutil.hpp +++ b/arbor/util/iterutil.hpp @@ -23,7 +23,7 @@ namespace util { * second is used when we can just return std::prev(end). */ template <typename I, typename E> -enable_if_t< +std::enable_if_t< is_forward_iterator<I>::value && (!is_bidirectional_iterator<E>::value || !std::is_constructible<I, E>::value), I> @@ -37,14 +37,14 @@ upto(I iter, E end) { } template <typename I, typename E> -enable_if_t<is_bidirectional_iterator<E>::value && std::is_constructible<I, E>::value, I> +std::enable_if_t<is_bidirectional_iterator<E>::value && std::is_constructible<I, E>::value, I> upto(I iter, E end) { return iter==I{end}? iter: I{std::prev(end)}; } template <typename I, typename E, typename C = common_random_access_iterator_t<I,E>> -enable_if_t<std::is_same<I, E>::value || +std::enable_if_t<std::is_same<I, E>::value || (has_common_random_access_iterator<I,E>::value && is_forward_iterator<I>::value), typename std::iterator_traits<C>::difference_type> @@ -53,7 +53,7 @@ distance(I first, E last) { } template <typename I, typename E> -enable_if_t<!has_common_random_access_iterator<I, E>::value && +std::enable_if_t<!has_common_random_access_iterator<I, E>::value && is_forward_iterator<I>::value, typename std::iterator_traits<I>::difference_type> distance(I first, E last) { @@ -70,16 +70,18 @@ distance(I first, E last) { * generic front() and back() methods for containers or ranges */ -// TODO: Use ADL begin and end when we avoid explicit return type in C++14 template <typename Seq> -auto front(Seq& seq) -> decltype(*std::begin(seq)) { - return *std::begin(seq); +decltype(auto) front(Seq& seq) { + using std::begin; + return *begin(seq); } -// TODO: Use ADL begin and end when we avoid explicit return type in C++14 template <typename Seq> -auto back(Seq& seq) -> decltype(*std::begin(seq)) { - return *upto(std::begin(seq), std::end(seq)); +decltype(auto) back(Seq& seq) { + using std::begin; + using std::end; + + return *upto(begin(seq), end(seq)); } /* diff --git a/arbor/util/maputil.hpp b/arbor/util/maputil.hpp index 223b400b..afb2f3ad 100644 --- a/arbor/util/maputil.hpp +++ b/arbor/util/maputil.hpp @@ -6,10 +6,10 @@ #include <utility> #include <type_traits> -#include <util/deduce_return.hpp> -#include <util/meta.hpp> #include <arbor/util/optional.hpp> -#include <util/transform.hpp> + +#include "util/meta.hpp" +#include "util/transform.hpp" // Convenience views, algorithms for maps and map-like containers. @@ -19,17 +19,18 @@ namespace util { // View over the keys (first elements) in a sequence of pairs or tuples. template <typename Seq> -auto keys(Seq&& m) DEDUCED_RETURN_TYPE(util::transform_view(std::forward<Seq>(m), util::first)) +auto keys(Seq&& m) { + return util::transform_view(std::forward<Seq>(m), util::first); +} // Is a container/sequence a map? -namespace impl { +namespace maputil_impl { template < typename C, typename seq_value = typename sequence_traits<C>::value_type, - typename K = typename std::tuple_element<0, seq_value>::type, - typename V = typename std::tuple_element<0, seq_value>::type, - typename find_value = decay_t<decltype(*std::declval<C>().find(std::declval<K>()))> + typename K = std::tuple_element_t<0, seq_value>, + typename find_value = std::decay_t<decltype(*std::declval<C>().find(std::declval<K>()))> > struct assoc_test: std::integral_constant<bool, std::is_same<seq_value, find_value>::value> {}; } @@ -38,7 +39,7 @@ template <typename Seq, typename = void> struct is_associative_container: std::false_type {}; template <typename Seq> -struct is_associative_container<Seq, void_t<impl::assoc_test<Seq>>>: impl::assoc_test<Seq> {}; +struct is_associative_container<Seq, void_t<maputil_impl::assoc_test<Seq>>>: maputil_impl::assoc_test<Seq> {}; // Find value in a sequence of key-value pairs or in a key-value assocation map, with // optional explicit comparator. @@ -50,29 +51,22 @@ struct is_associative_container<Seq, void_t<impl::assoc_test<Seq>>>: impl::assoc // 1. the sequence is an lvalue reference, and // 2. if the deduced return type from calling `get` on an entry from the sequence is an lvalue reference. -namespace impl { - // import std::get for ADL below. +namespace maputil_impl { + // import std::get and std::begin for ADL below. + using std::begin; using std::get; - // TODO: C++14 use std::equal_to<void> for this. - struct generic_equal_to { - template <typename A, typename B> - bool operator()(A&& a, B&& b) { - return std::forward<A>(a)==std::forward<B>(b); - } - }; - // use linear search template < typename Seq, typename Key, - typename Eq = generic_equal_to, - typename Ret0 = decltype(get<1>(*std::begin(std::declval<Seq&&>()))), - typename Ret = typename std::conditional< + typename Eq = std::equal_to<>, + typename Ret0 = decltype(get<1>(*begin(std::declval<Seq&&>()))), + typename Ret = std::conditional_t< std::is_rvalue_reference<Seq&&>::value || !std::is_lvalue_reference<Ret0>::value, - typename std::remove_reference<Ret0>::type, + std::remove_reference_t<Ret0>, Ret0 - >::type + > > optional<Ret> value_by_key(std::false_type, Seq&& seq, const Key& key, Eq eq=Eq{}) { for (auto&& entry: seq) { @@ -89,11 +83,11 @@ namespace impl { typename Key, typename FindRet = decltype(std::declval<Assoc&&>().find(std::declval<Key>())), typename Ret0 = decltype(get<1>(*std::declval<FindRet>())), - typename Ret = typename std::conditional< + typename Ret = std::conditional_t< std::is_rvalue_reference<Assoc&&>::value || !std::is_lvalue_reference<Ret0>::value, - typename std::remove_reference<Ret0>::type, + std::remove_reference_t<Ret0>, Ret0 - >::type + > > optional<Ret> value_by_key(std::true_type, Assoc&& map, const Key& key) { auto it = map.find(key); @@ -105,15 +99,16 @@ namespace impl { } template <typename C, typename Key, typename Eq> -auto value_by_key(C&& c, const Key& k, Eq eq) - DEDUCED_RETURN_TYPE(impl::value_by_key(std::false_type{}, std::forward<C>(c), k, eq)) +auto value_by_key(C&& c, const Key& k, Eq eq) { + return maputil_impl::value_by_key(std::false_type{}, std::forward<C>(c), k, eq); +} template <typename C, typename Key> -auto value_by_key(C&& c, const Key& k) - DEDUCED_RETURN_TYPE( - impl::value_by_key( - std::integral_constant<bool, is_associative_container<C>::value>{}, - std::forward<C>(c), k)) +auto value_by_key(C&& c, const Key& k) { + return maputil_impl::value_by_key( + std::integral_constant<bool, is_associative_container<C>::value>{}, + std::forward<C>(c), k); +} // Find the index into an ordered sequence of a value by binary search; // returns optional<size_type> for the size_type associated with the sequence. @@ -123,7 +118,7 @@ template <typename C, typename Key> optional<typename sequence_traits<C>::difference_type> binary_search_index(const C& c, const Key& key) { auto strict = strict_view(c); auto it = std::lower_bound(strict.begin(), strict.end(), key); - return it!=strict.end() && key==*it? util::just(std::distance(strict.begin(), it)): util::nullopt; + return it!=strict.end() && key==*it? just(std::distance(strict.begin(), it)): nullopt; } // Key equality helper for NUL-terminated strings. diff --git a/arbor/util/meta.hpp b/arbor/util/meta.hpp index f1debc43..957c3451 100644 --- a/arbor/util/meta.hpp +++ b/arbor/util/meta.hpp @@ -6,33 +6,18 @@ #include <iterator> #include <type_traits> - -#include "util/deduce_return.hpp" - namespace arb { namespace util { // The following classes and functions can be replaced // with std functions when we migrate to later versions of C++. // -// C++14: -// result_of_t, enable_if_t, decay_t, size, cbegin, cend. -// // C++17: // void_t, empty, data, as_const -template <typename T> -using result_of_t = typename std::result_of<T>::type; - -template <bool V, typename R = void> -using enable_if_t = typename std::enable_if<V, R>::type; - template <class...> using void_t = void; -template <typename T> -using decay_t = typename std::decay<T>::type; - template <typename X> constexpr std::size_t size(const X& x) { return x.size(); } @@ -40,10 +25,10 @@ template <typename X, std::size_t N> constexpr std::size_t size(X (&)[N]) noexcept { return N; } template <typename C> -constexpr auto data(C& c) -> decltype(c.data()) { return c.data(); } +constexpr auto data(C& c) { return c.data(); } template <typename C> -constexpr auto data(const C& c) -> decltype(c.data()) { return c.data(); } +constexpr auto data(const C& c) { return c.data(); } template <typename T, std::size_t N> constexpr T* data(T (&a)[N]) noexcept { return a; } @@ -52,29 +37,10 @@ template <typename T> void as_const(T&& t) = delete; template <typename T> -constexpr typename std::add_const<T>::type& as_const(T& t) { +constexpr std::add_const_t<T>& as_const(T& t) { return t; } -// Wrap cbegin, cend in inner namespace in order to properly invoke ADL. - -namespace impl { - using std::begin; - using std::end; - - template <typename T> - constexpr auto cbegin_(const T& c) DEDUCED_RETURN_TYPE(begin(c)) - - template <typename T> - constexpr auto cend_(const T& c) DEDUCED_RETURN_TYPE(end(c)) -} - -template <typename T> -constexpr auto cbegin(const T& c) DEDUCED_RETURN_TYPE(impl::cbegin_(c)) - -template <typename T> -constexpr auto cend(const T& c) DEDUCED_RETURN_TYPE(impl::cend_(c)) - // Use sequence `empty() const` method if exists, otherwise // compare begin and end. @@ -122,9 +88,12 @@ namespace impl_seqtrait { template <typename Seq, typename = void> struct data_returns_pointer: std::false_type {}; + template <typename T, std::size_t N> + struct data_returns_pointer<T (&)[N], void>: public std::true_type {}; + template <typename T> - struct data_returns_pointer<T, void_t<decltype(util::data(std::declval<T>()))>>: - public std::is_pointer<decltype(util::data(std::declval<T>()))>::type {}; + struct data_returns_pointer<T, void_t<decltype(std::declval<T>().data())>>: + public std::is_pointer<decltype(std::declval<T>().data())>::type {}; template <typename Seq> struct sequence_traits { @@ -139,41 +108,65 @@ namespace impl_seqtrait { using const_sentinel = decltype(end(std::declval<const Seq&>())); static constexpr bool is_contiguous = data_returns_pointer<Seq>::value; + static constexpr bool is_regular = std::is_same<iterator, sentinel>::value; }; + + template<typename T, typename V=void> + struct is_sequence: + std::false_type {}; + + template<typename T> + struct is_sequence<T, void_t<decltype(begin(std::declval<T>()))>>: + std::true_type {}; + } template <typename Seq> using sequence_traits = impl_seqtrait::sequence_traits<Seq>; +// Sequence test by checking begin. + +template <typename T> +using is_sequence = impl_seqtrait::is_sequence<T>; + +template <typename T> +using enable_if_sequence_t = std::enable_if_t<util::is_sequence<T>::value>; + +template <typename T> +using is_contiguous = std::integral_constant<bool, sequence_traits<T>::is_contiguous>; + +template <typename T> +using is_regular_sequence = std::integral_constant<bool, sequence_traits<T>::is_regular>; + // Convenience short cuts for `enable_if` template <typename T> using enable_if_copy_constructible_t = - enable_if_t<std::is_copy_constructible<T>::value>; + std::enable_if_t<std::is_copy_constructible<T>::value>; template <typename T> using enable_if_move_constructible_t = - enable_if_t<std::is_move_constructible<T>::value>; + std::enable_if_t<std::is_move_constructible<T>::value>; template <typename T> using enable_if_default_constructible_t = - enable_if_t<std::is_default_constructible<T>::value>; + std::enable_if_t<std::is_default_constructible<T>::value>; template <typename... T> using enable_if_constructible_t = - enable_if_t<std::is_constructible<T...>::value>; + std::enable_if_t<std::is_constructible<T...>::value>; template <typename T> using enable_if_copy_assignable_t = - enable_if_t<std::is_copy_assignable<T>::value>; + std::enable_if_t<std::is_copy_assignable<T>::value>; template <typename T> using enable_if_move_assignable_t = - enable_if_t<std::is_move_assignable<T>::value>; + std::enable_if_t<std::is_move_assignable<T>::value>; template <typename T> using enable_if_trivially_copyable_t = - enable_if_t<std::is_trivially_copyable<T>::value>; + std::enable_if_t<std::is_trivially_copyable<T>::value>; // Iterator class test // (might not be portable before C++17) @@ -194,7 +187,7 @@ template <typename T, typename = void> struct is_random_access_iterator: public std::false_type {}; template <typename T> -struct is_random_access_iterator<T, enable_if_t< +struct is_random_access_iterator<T, std::enable_if_t< std::is_same< std::random_access_iterator_tag, typename std::iterator_traits<T>::iterator_category>::value @@ -209,7 +202,7 @@ template <typename T, typename = void> struct is_bidirectional_iterator: public std::false_type {}; template <typename T> -struct is_bidirectional_iterator<T, enable_if_t< +struct is_bidirectional_iterator<T, std::enable_if_t< std::is_same< std::random_access_iterator_tag, typename std::iterator_traits<T>::iterator_category>::value @@ -228,7 +221,7 @@ template <typename T, typename = void> struct is_forward_iterator: public std::false_type {}; template <typename T> -struct is_forward_iterator<T, enable_if_t< +struct is_forward_iterator<T, std::enable_if_t< std::is_same< std::random_access_iterator_tag, typename std::iterator_traits<T>::iterator_category>::value @@ -254,13 +247,13 @@ struct common_random_access_iterator< I, E, void_t<decltype(false? std::declval<I>(): std::declval<E>())>, - util::enable_if_t< + std::enable_if_t< is_random_access_iterator< - decay_t<decltype(false? std::declval<I>(): std::declval<E>())> + std::decay_t<decltype(false? std::declval<I>(): std::declval<E>())> >::value > > { - using type = util::decay_t< + using type = std::decay_t< decltype(false ? std::declval<I>() : std::declval<E>()) >; }; @@ -276,17 +269,6 @@ template <typename I, typename E> struct has_common_random_access_iterator<I, E, void_t<util::common_random_access_iterator_t<I, E>>>: std::true_type {}; -template<typename T, typename V=void> -struct is_sequence: - std::false_type {}; - -template<typename T> -struct is_sequence<T, void_t<decltype(std::begin(std::declval<T>()))>>: - std::true_type {}; - -template <typename T> -using enable_if_sequence_t = util::enable_if_t<util::is_sequence<T>::value>; - // No generic lambdas in C++11, so some convenience accessors for pairs that // are type-generic diff --git a/arbor/util/partition.hpp b/arbor/util/partition.hpp index 0f1324a0..0f360fd2 100644 --- a/arbor/util/partition.hpp +++ b/arbor/util/partition.hpp @@ -99,7 +99,7 @@ private: template < typename Seq, typename SeqIter = typename sequence_traits<Seq>::const_iterator, - typename = enable_if_t<is_forward_iterator<SeqIter>::value> + typename = std::enable_if_t<is_forward_iterator<SeqIter>::value> > partition_range<SeqIter> partition_view(const Seq& r) { return partition_range<SeqIter>(r); diff --git a/arbor/util/partition_iterator.hpp b/arbor/util/partition_iterator.hpp index 1f23f718..8b187e56 100644 --- a/arbor/util/partition_iterator.hpp +++ b/arbor/util/partition_iterator.hpp @@ -31,7 +31,7 @@ public: const I& inner() const { return inner_; } I& inner() { return inner_; } - using inner_value_type = decay_t<decltype(*inner_)>; + using inner_value_type = std::decay_t<decltype(*inner_)>; using typename base::difference_type; using value_type = std::pair<inner_value_type, inner_value_type>; @@ -42,7 +42,7 @@ public: template < typename J, - typename = enable_if_t<!std::is_same<decay_t<J>, partition_iterator>::value> + typename = std::enable_if_t<!std::is_same<std::decay_t<J>, partition_iterator>::value> > explicit partition_iterator(J&& c): inner_{std::forward<J>(c)} {} diff --git a/arbor/util/range.hpp b/arbor/util/range.hpp index a47537bd..fbec6108 100644 --- a/arbor/util/range.hpp +++ b/arbor/util/range.hpp @@ -47,7 +47,7 @@ struct range { using sentinel = S; using const_iterator = iterator; using difference_type = typename std::iterator_traits<iterator>::difference_type; - using size_type = typename std::make_unsigned<difference_type>::type; + using size_type = std::make_unsigned_t<difference_type>; using value_type = typename std::iterator_traits<iterator>::value_type; using reference = typename std::iterator_traits<iterator>::reference; using const_reference = const value_type&; @@ -67,7 +67,7 @@ struct range { template < typename U1, typename U2, - typename = enable_if_t< + typename = std::enable_if_t< std::is_constructible<iterator, U1>::value && std::is_constructible<sentinel, U2>::value> > @@ -94,7 +94,7 @@ struct range { sentinel cend() const { return right; } template <typename V = iterator> - enable_if_t<is_forward_iterator<V>::value, size_type> + std::enable_if_t<is_forward_iterator<V>::value, size_type> size() const { return util::distance(begin(), end()); } @@ -108,18 +108,18 @@ struct range { std::swap(right, other.right); } - auto front() const -> decltype(*left) { return *left; } + decltype(auto) front() const { return *left; } - auto back() const -> decltype(*left) { return *upto(left, right); } + decltype(auto) back() const { return *upto(left, right); } template <typename V = iterator> - enable_if_t<is_random_access_iterator<V>::value, decltype(*left)> + std::enable_if_t<is_random_access_iterator<V>::value, decltype(*left)> operator[](difference_type n) const { return *std::next(begin(), n); } template <typename V = iterator> - enable_if_t<is_random_access_iterator<V>::value, decltype(*left)> + std::enable_if_t<is_random_access_iterator<V>::value, decltype(*left)> at(difference_type n) const { if (size_type(n) >= size()) { throw std::out_of_range("out of range in range"); @@ -129,7 +129,7 @@ struct range { // Expose `data` method if a pointer range. template <typename V = iterator, typename W = sentinel> - enable_if_t<std::is_same<V, W>::value && std::is_pointer<V>::value, iterator> + std::enable_if_t<std::is_same<V, W>::value && std::is_pointer<V>::value, iterator> data() const { return left; } @@ -137,7 +137,7 @@ struct range { #ifdef ARB_HAVE_TBB template < typename V = iterator, - typename = enable_if_t<is_forward_iterator<V>::value> + typename = std::enable_if_t<is_forward_iterator<V>::value> > range(range& r, tbb::split): left(r.left), right(r.right) @@ -148,7 +148,7 @@ struct range { template < typename V = iterator, - typename = enable_if_t<is_forward_iterator<V>::value> + typename = std::enable_if_t<is_forward_iterator<V>::value> > range(range& r, tbb::proportional_split p): left(r.left), right(r.right) @@ -184,37 +184,28 @@ range<U, V> make_range(const std::pair<U, V>& iterators) { // Present a possibly sentinel-terminated range as an STL-compatible sequence // using the sentinel_iterator adaptor. -// TODO: ADL begin/end with C++14 deduced return. template <typename Seq> -auto canonical_view(Seq& s) -> - range<sentinel_iterator_t<decltype(std::begin(s)), decltype(std::end(s))>> -{ - return {make_sentinel_iterator(std::begin(s), std::end(s)), make_sentinel_end(std::begin(s), std::end(s))}; -} +auto canonical_view(Seq&& s) { + using std::begin; + using std::end; -template <typename Seq> -auto canonical_view(const Seq& s) -> - range<sentinel_iterator_t<decltype(std::begin(s)), decltype(std::end(s))>> -{ - return {make_sentinel_iterator(std::begin(s), std::end(s)), make_sentinel_end(std::begin(s), std::end(s))}; + return make_range( + make_sentinel_iterator(begin(s), end(s)), + make_sentinel_end(begin(s), end(s))); } // Strictly evaluate end point in sentinel-terminated range and present as a range over // iterators. Note: O(N) behaviour with forward iterator ranges or sentinel-terminated ranges. template <typename Seq> -auto strict_view(Seq&& s) -> range<decltype(std::begin(s))> -{ - return make_range(std::begin(s), std::begin(s)==std::end(s)? std::begin(s): std::next(util::upto(std::begin(s), std::end(s)))); -} +auto strict_view(Seq&& s) { + using std::begin; + using std::end; -#if 0 -template <typename Seq> -auto strict_view(const Seq& s) -> range<decltype(std::begin(s))> -{ - return make_range(std::begin(s), std::begin(s)==std::end(s)? std::begin(s): std::next(util::upto(std::begin(s), std::end(s)))); + auto b = begin(s); + auto e = end(s); + return make_range(b, b==e? b: std::next(util::upto(b, e))); } -#endif } // namespace util } // namespace arb diff --git a/arbor/util/rangeutil.hpp b/arbor/util/rangeutil.hpp index 1979380c..25e74a0c 100644 --- a/arbor/util/rangeutil.hpp +++ b/arbor/util/rangeutil.hpp @@ -10,11 +10,9 @@ #include <ostream> #include <numeric> -#include <util/deduce_return.hpp> -#include <util/meta.hpp> -#include <util/range.hpp> -#include <util/transform.hpp> -#include <util/meta.hpp> +#include "util/meta.hpp" +#include "util/range.hpp" +#include "util/transform.hpp" namespace arb { namespace util { @@ -39,9 +37,10 @@ range_view(Seq&& seq) { return make_range(std::begin(seq), std::end(seq)); } -template <typename Seq, typename = enable_if_t<sequence_traits<Seq&&>::is_contiguous>> -auto range_pointer_view(Seq&& seq) - DEDUCED_RETURN_TYPE(make_range(util::data(seq), util::data(seq)+util::size(seq))) +template <typename Seq, typename = std::enable_if_t<sequence_traits<Seq&&>::is_contiguous>> +auto range_pointer_view(Seq&& seq) { + return make_range(util::data(seq), util::data(seq)+util::size(seq)); +} template < typename Seq, @@ -49,7 +48,7 @@ template < typename Offset2, typename Iter = typename sequence_traits<Seq&&>::iterator > -enable_if_t<is_forward_iterator<Iter>::value, range<Iter>> +std::enable_if_t<is_forward_iterator<Iter>::value, range<Iter>> subrange_view(Seq&& seq, Offset1 bi, Offset2 ei) { Iter b = std::begin(seq); std::advance(b, bi); @@ -65,7 +64,7 @@ template < typename Offset2, typename Iter = typename sequence_traits<Seq&&>::iterator > -enable_if_t<is_forward_iterator<Iter>::value, range<Iter>> +std::enable_if_t<is_forward_iterator<Iter>::value, range<Iter>> subrange_view(Seq&& seq, std::pair<Offset1, Offset2> index) { return subrange_view(std::forward<Seq>(seq), index.first, index.second); } @@ -88,7 +87,7 @@ void fill(Seq&& seq, const V& value) { template <typename Container, typename Seq> Container& append(Container &c, const Seq& seq) { auto canon = canonical_view(seq); - c.insert(c.end(), std::begin(canon), std::end(canon)); + c.insert(c.end(), canon.begin(), canon.end()); return c; } @@ -139,28 +138,28 @@ AssignableContainer& assign_by(AssignableContainer& c, const Seq& seq, const Pro // Note that a const range reference may wrap non-const iterators. template <typename Seq> -enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> +std::enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> sort(Seq&& seq) { auto canon = canonical_view(seq); - std::sort(std::begin(canon), std::end(canon)); + std::sort(canon.begin(), canon.end()); } template <typename Seq, typename Less> -enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> +std::enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> sort(Seq&& seq, const Less& less) { auto canon = canonical_view(seq); - std::sort(std::begin(canon), std::end(canon), less); + std::sort(canon.begin(), canon.end(), less); } // Sort in-place by projection `proj` template <typename Seq, typename Proj> -enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> +std::enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> sort_by(Seq&& seq, const Proj& proj) { using value_type = typename sequence_traits<Seq&&>::value_type; auto canon = canonical_view(seq); - std::sort(std::begin(canon), std::end(canon), + std::sort(canon.begin(), canon.end(), [&proj](const value_type& a, const value_type& b) { return proj(a) < proj(b); }); @@ -169,12 +168,12 @@ sort_by(Seq&& seq, const Proj& proj) { // Stable sort in-place by projection `proj` template <typename Seq, typename Proj> -enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> +std::enable_if_t<!std::is_const<typename sequence_traits<Seq&&>::reference>::value> stable_sort_by(Seq&& seq, const Proj& proj) { using value_type = typename sequence_traits<Seq&&>::value_type; auto canon = canonical_view(seq); - std::stable_sort(std::begin(canon), std::end(canon), + std::stable_sort(canon.begin(), canon.end(), [&proj](const value_type& a, const value_type& b) { return proj(a) < proj(b); }); @@ -185,13 +184,13 @@ stable_sort_by(Seq&& seq, const Proj& proj) { template <typename Seq, typename Predicate> bool all_of(const Seq& seq, const Predicate& pred) { auto canon = canonical_view(seq); - return std::all_of(std::begin(canon), std::end(canon), pred); + return std::all_of(canon.begin(), canon.end(), pred); } template <typename Seq, typename Predicate> bool any_of(const Seq& seq, const Predicate& pred) { auto canon = canonical_view(seq); - return std::any_of(std::begin(canon), std::end(canon), pred); + return std::any_of(canon.begin(), canon.end(), pred); } // Accumulate by projection `proj` @@ -203,7 +202,7 @@ template < > Value sum_by(const Seq& seq, const Proj& proj, Value base = Value{}) { auto canon = canonical_view(transform_view(seq, proj)); - return std::accumulate(std::begin(canon), std::end(canon), base); + return std::accumulate(canon.begin(), canon.end(), base); } // Maximum element by projection `proj` @@ -216,7 +215,7 @@ max_element_by(Seq&& seq, const Proj& proj) { using value_type = typename sequence_traits<Seq&&>::value_type; auto canon = canonical_view(seq); - return std::max_element(std::begin(canon), std::end(canon), + return std::max_element(canon.begin(), canon.end(), [&proj](const value_type& a, const value_type& b) { return proj(a) < proj(b); }); @@ -237,12 +236,15 @@ template < typename Compare = std::less<Value> > Value max_value(const Seq& seq, Compare cmp = Compare{}) { + using std::begin; + using std::end; + if (util::empty(seq)) { return Value{}; } - auto i = std::begin(seq); - auto e = std::end(seq); + auto i = begin(seq); + auto e = end(seq); Value m = *i; while (++i!=e) { Value x = *i; @@ -261,12 +263,15 @@ template < typename Compare = std::less<Value> > std::pair<Value, Value> minmax_value(const Seq& seq, Compare cmp = Compare{}) { + using std::begin; + using std::end; + if (util::empty(seq)) { return {Value{}, Value{}}; } - auto i = std::begin(seq); - auto e = std::end(seq); + auto i = begin(seq); + auto e = end(seq); Value lower = *i; Value upper = *i; while (++i!=e) { @@ -286,7 +291,7 @@ std::pair<Value, Value> minmax_value(const Seq& seq, Compare cmp = Compare{}) { template <typename Seq, typename = util::enable_if_sequence_t<const Seq&>> bool is_sorted(const Seq& seq) { auto canon = canonical_view(seq); - return std::is_sorted(std::begin(canon), std::end(canon)); + return std::is_sorted(canon.begin(), canon.end()); } @@ -297,11 +302,14 @@ bool is_sorted(const Seq& seq) { template < typename Seq, typename Proj, - typename Compare = std::less<typename std::result_of<Proj (typename sequence_traits<const Seq&>::value_type)>::type> + typename Compare = std::less<std::result_of_t<Proj (typename sequence_traits<const Seq&>::value_type)>> > bool is_sorted_by(const Seq& seq, const Proj& proj, Compare cmp = Compare{}) { - auto i = std::begin(seq); - auto e = std::end(seq); + using std::begin; + using std::end; + + auto i = begin(seq); + auto e = end(seq); if (i==e) { return true; diff --git a/arbor/util/scope_exit.hpp b/arbor/util/scope_exit.hpp index 2bd619fb..5f83678a 100644 --- a/arbor/util/scope_exit.hpp +++ b/arbor/util/scope_exit.hpp @@ -14,7 +14,7 @@ namespace util { template < typename F, - typename = typename std::enable_if<std::is_nothrow_move_constructible<F>::value>::type + typename = std::enable_if_t<std::is_nothrow_move_constructible<F>::value> > class scope_exit { F on_exit; @@ -23,7 +23,7 @@ class scope_exit { public: template < typename F2, - typename = typename std::enable_if<std::is_nothrow_constructible<F, F2>::value>::type + typename = std::enable_if_t<std::is_nothrow_constructible<F, F2>::value> > explicit scope_exit(F2&& f) noexcept: on_exit(std::forward<F2>(f)) {} @@ -44,8 +44,8 @@ public: }; template <typename F> -scope_exit<typename std::decay<F>::type> on_scope_exit(F&& f) { - return scope_exit<typename std::decay<F>::type>(std::forward<F>(f)); +scope_exit<std::decay_t<F>> on_scope_exit(F&& f) { + return scope_exit<std::decay_t<F>>(std::forward<F>(f)); } } // namespace util diff --git a/arbor/util/sentinel.hpp b/arbor/util/sentinel.hpp index 110dc567..09b98513 100644 --- a/arbor/util/sentinel.hpp +++ b/arbor/util/sentinel.hpp @@ -58,7 +58,7 @@ public: sentinel_iterator(I i): e_(i) {} - template <typename V = S, typename = enable_if_t<!std::is_same<I, V>::value>> + template <typename V = S, typename = std::enable_if_t<!std::is_same<I, V>::value>> sentinel_iterator(S i): e_(i) {} sentinel_iterator() = default; @@ -70,7 +70,7 @@ public: // forward and input iterator requirements - auto operator*() const -> decltype(*(this->iter())) { return *iter(); } + decltype(auto) operator*() const { return *iter(); } I operator->() const { return e_.template ptr<0>(); } @@ -141,7 +141,7 @@ public: return iter()-x.iter(); } - auto operator[](difference_type n) const -> decltype(*(this->iter())) { + decltype(auto) operator[](difference_type n) const { return *(iter()+n); } @@ -174,7 +174,7 @@ public: template <typename I, typename S> using sentinel_iterator_t = - typename std::conditional<std::is_same<I, S>::value, I, sentinel_iterator<I, S>>::type; + std::conditional_t<std::is_same<I, S>::value, I, sentinel_iterator<I, S>>; template <typename I, typename S> sentinel_iterator_t<I, S> make_sentinel_iterator(const I& i, const S& s) { diff --git a/arbor/util/span.hpp b/arbor/util/span.hpp index 7a572cbc..817e1acf 100644 --- a/arbor/util/span.hpp +++ b/arbor/util/span.hpp @@ -7,10 +7,9 @@ #include <type_traits> #include <utility> -#include <util/counter.hpp> -#include <util/deduce_return.hpp> -#include <util/meta.hpp> -#include <util/range.hpp> +#include "util/counter.hpp" +#include "util/meta.hpp" +#include "util/range.hpp" namespace arb { namespace util { @@ -24,13 +23,13 @@ template <typename I> using span = range<counter<I>>; template <typename I, typename J> -span<typename std::common_type<I, J>::type> make_span(I left, J right) { - return span<typename std::common_type<I, J>::type>(left, right); +span<std::common_type_t<I, J>> make_span(I left, J right) { + return span<std::common_type_t<I, J>>(left, right); } template <typename I, typename J> -span<typename std::common_type<I, J>::type> make_span(std::pair<I, J> interval) { - return span<typename std::common_type<I, J>::type>(interval.first, interval.second); +span<std::common_type_t<I, J>> make_span(std::pair<I, J> interval) { + return span<std::common_type_t<I, J>>(interval.first, interval.second); } template <typename I> @@ -39,7 +38,9 @@ span<I> make_span(I right) { } template <typename Seq> -auto count_along(const Seq& s) DEDUCED_RETURN_TYPE(util::make_span(util::size(s))) +auto count_along(const Seq& s) { + return util::make_span(util::size(s)); +} } // namespace util } // namespace arb diff --git a/arbor/util/transform.hpp b/arbor/util/transform.hpp index c91dbba7..ed436973 100644 --- a/arbor/util/transform.hpp +++ b/arbor/util/transform.hpp @@ -35,16 +35,16 @@ class transform_iterator: public iterator_adaptor<transform_iterator<I, F>, I> { I& inner() { return inner_; } using inner_value_type = decltype(*inner_); - using raw_value_type = typename std::result_of<F (inner_value_type)>::type; + using raw_value_type = std::result_of_t<F (inner_value_type)>; static constexpr bool present_lvalue = std::is_reference<raw_value_type>::value; public: using typename base::difference_type; - using value_type = util::decay_t<raw_value_type>; - using pointer = typename std::conditional<present_lvalue, value_type*, const value_type*>::type; - using reference = typename std::conditional<present_lvalue, raw_value_type, const value_type&>::type; + using value_type = std::decay_t<raw_value_type>; + using pointer = std::conditional_t<present_lvalue, value_type*, const value_type*>; + using reference = std::conditional_t<present_lvalue, raw_value_type, const value_type&>; transform_iterator() = default; @@ -80,17 +80,17 @@ public: // forward and input iterator requirements - typename std::conditional<present_lvalue, reference, value_type>::type + std::conditional_t<present_lvalue, reference, value_type> operator*() const { return f_.cref()(*inner_); } - typename std::conditional<present_lvalue, pointer, util::pointer_proxy<value_type>>::type + std::conditional_t<present_lvalue, pointer, util::pointer_proxy<value_type>> operator->() const { return pointer_impl(std::integral_constant<bool, present_lvalue>{}); } - typename std::conditional<present_lvalue, reference, value_type>::type + std::conditional_t<present_lvalue, reference, value_type> operator[](difference_type n) const { return *(*this+n); } @@ -121,32 +121,31 @@ private: }; template <typename I, typename F> -transform_iterator<I, util::decay_t<F>> make_transform_iterator(const I& i, const F& f) { - return transform_iterator<I, util::decay_t<F>>(i, f); +transform_iterator<I, std::decay_t<F>> make_transform_iterator(const I& i, const F& f) { + return transform_iterator<I, std::decay_t<F>>(i, f); } -template < - typename Seq, - typename F, - typename seq_iter = typename sequence_traits<Seq>::iterator, - typename seq_sent = typename sequence_traits<Seq>::sentinel, - typename = enable_if_t<std::is_same<seq_iter, seq_sent>::value> -> -range<transform_iterator<seq_iter, util::decay_t<F>>> -transform_view(Seq&& s, const F& f) { - return {make_transform_iterator(std::begin(s), f), make_transform_iterator(std::end(s), f)}; +// TODO C++17: simplify with constexpr-if +namespace transform_impl { + using std::begin; + using std::end; + + // transform over regular sequences: + template <typename Seq, typename F> + auto transform_(Seq&& s, const F& f, std::true_type) { + return make_range(make_transform_iterator(begin(s), f), make_transform_iterator(end(s), f)); + } + + // transform over sentinel-terminated sequences: + template <typename Seq, typename F> + auto transform_(Seq&& s, const F& f, std::false_type) { + return make_range(make_transform_iterator(begin(s), f), end(s)); + } } -template < - typename Seq, - typename F, - typename seq_iter = typename sequence_traits<Seq>::iterator, - typename seq_sent = typename sequence_traits<Seq>::sentinel, - typename = enable_if_t<!std::is_same<seq_iter, seq_sent>::value> -> -range<transform_iterator<seq_iter, util::decay_t<F>>, seq_sent> -transform_view(Seq&& s, const F& f) { - return {make_transform_iterator(std::begin(s), f), std::end(s)}; +template <typename Seq, typename F> +auto transform_view(Seq&& s, const F& f) { + return transform_impl::transform_(std::forward<Seq>(s), f, is_regular_sequence<Seq&&>{}); } } // namespace util diff --git a/aux/tinyopt.hpp b/aux/tinyopt.hpp index 058bd2cc..8bb6fc24 100644 --- a/aux/tinyopt.hpp +++ b/aux/tinyopt.hpp @@ -69,7 +69,7 @@ auto keywords(const KeywordPairs& pairs) -> keyword_parser<decltype(std::begin(p return keyword_parser<decltype(std::begin(pairs)->second)>(pairs); } -template <typename V = std::string, typename P = default_parser<V>, typename = typename std::enable_if<!std::is_same<V, void>::value>::type> +template <typename V = std::string, typename P = default_parser<V>, typename = std::enable_if_t<!std::is_same<V, void>::value>> optional<V> parse_opt(char **& argp, char shortopt, const char* longopt=nullptr, const P& parse = P{}) { const char* arg = argp[0]; diff --git a/example/brunel/brunel_miniapp.cpp b/example/brunel/brunel_miniapp.cpp index ef07bf2c..ae716caf 100644 --- a/example/brunel/brunel_miniapp.cpp +++ b/example/brunel/brunel_miniapp.cpp @@ -15,7 +15,6 @@ #include <arbor/recipe.hpp> #include <arbor/simulation.hpp> #include <arbor/threadinfo.hpp> -#include <arbor/util/make_unique.hpp> #include <arbor/version.hpp> #include "json_meter.hpp" @@ -242,7 +241,7 @@ int main(int argc, char** argv) { brunel_recipe recipe(nexc, ninh, next, in_degree_prop, w, d, rel_inh_strength, poiss_lambda, seed); auto register_exporter = [] (const io::cl_options& options) { - return util::make_unique<io::exporter_spike_file> + return std::make_unique<io::exporter_spike_file> (options.file_name, options.output_path, options.file_extension, options.over_write); }; diff --git a/example/brunel/io.cpp b/example/brunel/io.cpp index c4940320..82624cd7 100644 --- a/example/brunel/io.cpp +++ b/example/brunel/io.cpp @@ -10,7 +10,6 @@ #include <tclap/CmdLine.h> #include <arbor/util/optional.hpp> -#include "util/meta.hpp" #include "io.hpp" // Let TCLAP understand value arguments that are of an optional type. @@ -69,7 +68,7 @@ namespace arb { template < typename T, typename Arg, - typename = util::enable_if_t<std::is_base_of<TCLAP::Arg, Arg>::value> + typename = std::enable_if_t<std::is_base_of<TCLAP::Arg, Arg>::value> > static void update_option(T& opt, Arg& arg) { if (arg.isSet()) { diff --git a/example/miniapp/io.cpp b/example/miniapp/io.cpp index e17cfdfc..ac171ca5 100644 --- a/example/miniapp/io.cpp +++ b/example/miniapp/io.cpp @@ -13,9 +13,6 @@ #include <arbor/util/optional.hpp> -#include "util/meta.hpp" -#include "util/strprintf.hpp" - #include "io.hpp" // Let TCLAP understand value arguments that are of an optional type. @@ -77,7 +74,7 @@ public: template < typename T, typename Arg, - typename = util::enable_if_t<std::is_base_of<TCLAP::Arg, Arg>::value> + typename = std::enable_if_t<std::is_base_of<TCLAP::Arg, Arg>::value> > static void update_option(T& opt, Arg& arg) { if (arg.isSet()) { diff --git a/example/miniapp/miniapp.cpp b/example/miniapp/miniapp.cpp index 2fb8be9c..c1095b08 100644 --- a/example/miniapp/miniapp.cpp +++ b/example/miniapp/miniapp.cpp @@ -82,7 +82,7 @@ int main(int argc, char** argv) { auto register_exporter = [] (const io::cl_options& options) { return - util::make_unique<io::exporter_spike_file>( + std::make_unique<io::exporter_spike_file>( options.file_name, options.output_path, options.file_extension, options.over_write); }; diff --git a/include/arbor/common_types.hpp b/include/arbor/common_types.hpp index 923cf6b6..418ba786 100644 --- a/include/arbor/common_types.hpp +++ b/include/arbor/common_types.hpp @@ -21,7 +21,7 @@ using cell_gid_type = std::uint32_t; // For sizes of collections of cells. -using cell_size_type = typename std::make_unsigned<cell_gid_type>::type; +using cell_size_type = std::make_unsigned_t<cell_gid_type>; // For indexes into cell-local data. // @@ -32,7 +32,7 @@ using cell_lid_type = std::uint32_t; // For counts of cell-local data. -using cell_local_size_type = typename std::make_unsigned<cell_lid_type>::type; +using cell_local_size_type = std::make_unsigned_t<cell_lid_type>; // For global identification of an item of cell local data. // diff --git a/include/arbor/constants.hpp b/include/arbor/constants.hpp index a761f369..45a38752 100644 --- a/include/arbor/constants.hpp +++ b/include/arbor/constants.hpp @@ -14,8 +14,6 @@ namespace constant { // 2010 8.3144621 96485.3365 // 2014 8.3144598 96485.33289 -// TODO: use value templates from C++14 - // Universal gas constant (R) // https://physics.nist.gov/cgi-bin/cuu/Value?r constexpr double gas_constant = 8.3144598; // J.K^-1.mol^-1 diff --git a/include/arbor/generic_event.hpp b/include/arbor/generic_event.hpp index 77ef4328..5eb3c25a 100644 --- a/include/arbor/generic_event.hpp +++ b/include/arbor/generic_event.hpp @@ -44,27 +44,27 @@ namespace arb { template <typename Event> -auto event_time(const Event& ev) -> decltype(ev.time) { +auto event_time(const Event& ev) { return ev.time; } template <typename Event> -auto event_index(const Event& ev) -> decltype(ev.index) { +auto event_index(const Event& ev) { return ev.index; } template <typename Event> -auto event_data(const Event& ev) -> decltype(ev.data) { +auto event_data(const Event& ev) { return ev.data; } struct event_time_less { - template <typename T, typename Event, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> + template <typename T, typename Event, typename = std::enable_if_t<std::is_floating_point<T>::value>> bool operator() (T l, const Event& r) { return l<event_time(r); } - template <typename T, typename Event, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> + template <typename T, typename Event, typename = std::enable_if_t<std::is_floating_point<T>::value>> bool operator() (const Event& l, T r) { return event_time(l)<r; } diff --git a/include/arbor/mc_segment.hpp b/include/arbor/mc_segment.hpp index c28ec316..7a0a7c28 100644 --- a/include/arbor/mc_segment.hpp +++ b/include/arbor/mc_segment.hpp @@ -14,7 +14,6 @@ #include <arbor/morphology.hpp> #include <arbor/mechinfo.hpp> #include <arbor/point.hpp> -#include <arbor/util/make_unique.hpp> #include <arbor/util/optional.hpp> namespace arb { @@ -176,7 +175,7 @@ public: std::unique_ptr<mc_segment> clone() const override { // use default copy constructor - return util::make_unique<placeholder_segment>(*this); + return std::make_unique<placeholder_segment>(*this); } bool is_placeholder() const override @@ -201,7 +200,7 @@ public: std::unique_ptr<mc_segment> clone() const override { // use default copy constructor - return util::make_unique<soma_segment>(*this); + return std::make_unique<soma_segment>(*this); } value_type radius() const @@ -284,7 +283,7 @@ public: std::unique_ptr<mc_segment> clone() const override { // use default copy constructor - return util::make_unique<cable_segment>(*this); + return std::make_unique<cable_segment>(*this); } value_type length() const diff --git a/include/arbor/mechinfo.hpp b/include/arbor/mechinfo.hpp index 2ee9faa9..41a3c631 100644 --- a/include/arbor/mechinfo.hpp +++ b/include/arbor/mechinfo.hpp @@ -11,7 +11,6 @@ #include <vector> #include <arbor/ion.hpp> -#include <arbor/util/enumhash.hpp> namespace arb { @@ -30,19 +29,6 @@ struct mechanism_field_spec { double upper_bound = std::numeric_limits<double>::max(); bool valid(double x) const { return x>=lower_bound && x<=upper_bound; } - - // TODO: C++14 - no need for ctor below, as aggregate initialization - // will work with default member initializers. - - mechanism_field_spec( - enum field_kind kind = parameter, - std::string units = "", - double default_value = 0., - double lower_bound = std::numeric_limits<double>::lowest(), - double upper_bound = std::numeric_limits<double>::max() - ): - kind(kind), units(units), default_value(default_value), lower_bound(lower_bound), upper_bound(upper_bound) - {} }; struct ion_dependency { @@ -71,7 +57,7 @@ struct mechanism_info { std::unordered_map<std::string, mechanism_field_spec> state; // Ion dependencies. - std::unordered_map<ionKind, ion_dependency, util::enum_hash> ions; + std::unordered_map<ionKind, ion_dependency> ions; mechanism_fingerprint fingerprint; }; diff --git a/include/arbor/simd/avx512.hpp b/include/arbor/simd/avx512.hpp index dd723c3f..0f062d11 100644 --- a/include/arbor/simd/avx512.hpp +++ b/include/arbor/simd/avx512.hpp @@ -344,7 +344,7 @@ struct avx512_int8: implbase<avx512_int8> { using is_int8_simd = std::integral_constant<bool, std::is_same<int, typename Impl::scalar_type>::value && Impl::width==8>; template <typename ImplIndex, - typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static __m512i gather(tag<ImplIndex>, const int32* p, const typename ImplIndex::vector_type& index) { int32 o[16]; ImplIndex::copy_to(index, o); @@ -353,7 +353,7 @@ struct avx512_int8: implbase<avx512_int8> { } template <typename ImplIndex, - typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static __m512i gather(tag<ImplIndex>, const __m512i& a, const int32* p, const typename ImplIndex::vector_type& index, const __mmask8& mask) { int32 o[16]; ImplIndex::copy_to(index, o); @@ -362,7 +362,7 @@ struct avx512_int8: implbase<avx512_int8> { } template <typename ImplIndex, - typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static void scatter(tag<ImplIndex>, const __m512i& s, int32* p, const typename ImplIndex::vector_type& index) { int32 o[16]; ImplIndex::copy_to(index, o); @@ -371,7 +371,7 @@ struct avx512_int8: implbase<avx512_int8> { } template <typename ImplIndex, - typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static void scatter(tag<ImplIndex>, const __m512i& s, int32* p, const typename ImplIndex::vector_type& index, const __mmask8& mask) { int32 o[16]; ImplIndex::copy_to(index, o); @@ -527,7 +527,7 @@ struct avx512_double8: implbase<avx512_double8> { template <typename Impl> using is_int8_simd = std::integral_constant<bool, std::is_same<int, typename Impl::scalar_type>::value && Impl::width==8>; - template <typename ImplIndex, typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + template <typename ImplIndex, typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static __m512d gather(tag<ImplIndex>, const double* p, const typename ImplIndex::vector_type& index) { int o[8]; ImplIndex::copy_to(index, o); @@ -535,7 +535,7 @@ struct avx512_double8: implbase<avx512_double8> { return _mm512_i32gather_pd(_mm256_loadu_si256(op), p, 8); } - template <typename ImplIndex, typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + template <typename ImplIndex, typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static __m512d gather(tag<ImplIndex>, const __m512d& a, const double* p, const typename ImplIndex::vector_type& index, const __mmask8& mask) { int o[8]; ImplIndex::copy_to(index, o); @@ -543,7 +543,7 @@ struct avx512_double8: implbase<avx512_double8> { return _mm512_mask_i32gather_pd(a, mask, _mm256_loadu_si256(op), p, 8); } - template <typename ImplIndex, typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + template <typename ImplIndex, typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static void scatter(tag<ImplIndex>, const __m512d& s, double* p, const typename ImplIndex::vector_type& index) { int o[8]; ImplIndex::copy_to(index, o); @@ -551,7 +551,7 @@ struct avx512_double8: implbase<avx512_double8> { _mm512_i32scatter_pd(p, _mm256_loadu_si256(op), s, 8); } - template <typename ImplIndex, typename = typename std::enable_if<is_int8_simd<ImplIndex>::value>::type> + template <typename ImplIndex, typename = std::enable_if_t<is_int8_simd<ImplIndex>::value>> static void scatter(tag<ImplIndex>, const __m512d& s, double* p, const typename ImplIndex::vector_type& index, const __mmask8& mask) { int o[8]; ImplIndex::copy_to(index, o); diff --git a/include/arbor/simd/implbase.hpp b/include/arbor/simd/implbase.hpp index 3722ae58..ebdf6552 100644 --- a/include/arbor/simd/implbase.hpp +++ b/include/arbor/simd/implbase.hpp @@ -31,6 +31,7 @@ #include <cmath> #include <algorithm> #include <iterator> +#include <type_traits> // Derived class I must at minimum provide: // diff --git a/include/arbor/simd/simd.hpp b/include/arbor/simd/simd.hpp index 2bb0c0bb..fff3ff08 100644 --- a/include/arbor/simd/simd.hpp +++ b/include/arbor/simd/simd.hpp @@ -108,18 +108,18 @@ namespace simd_detail { } // Construct from a different SIMD value by casting. - template <typename Other, typename = typename std::enable_if<width==simd_traits<Other>::width>::type> + template <typename Other, typename = std::enable_if_t<width==simd_traits<Other>::width>> explicit simd_impl(const simd_impl<Other>& x) { value_ = Impl::cast_from(tag<Other>{}, x.value_); } // Construct from indirect expression (gather). - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> explicit simd_impl(indirect_expression<IndexImpl, scalar_type> pi) { copy_from(pi); } - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> explicit simd_impl(indirect_expression<IndexImpl, const scalar_type> pi) { copy_from(pi); } @@ -147,7 +147,7 @@ namespace simd_detail { Impl::copy_to(value_, p); } - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> void copy_to(indirect_expression<IndexImpl, scalar_type> pi) const { Impl::scatter(tag<IndexImpl>{}, value_, pi.p, pi.index); } @@ -156,7 +156,7 @@ namespace simd_detail { value_ = Impl::copy_from(p); } - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> void copy_from(indirect_expression<IndexImpl, scalar_type> pi) { switch (pi.constraint) { case index_constraint::none: @@ -181,7 +181,7 @@ namespace simd_detail { } } - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> void copy_from(indirect_expression<IndexImpl, const scalar_type> pi) { switch (pi.constraint) { case index_constraint::none: @@ -384,12 +384,12 @@ namespace simd_detail { // Gather and scatter. - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> void copy_from(indirect_expression<IndexImpl, scalar_type> pi) { data_.value_ = Impl::gather(tag<IndexImpl>{}, data_.value_, pi.p, pi.index, mask_.value_); } - template <typename IndexImpl, typename = typename std::enable_if<width==simd_traits<IndexImpl>::width>::type> + template <typename IndexImpl, typename = std::enable_if_t<width==simd_traits<IndexImpl>::width>> void copy_to(indirect_expression<IndexImpl, scalar_type> pi) const { Impl::scatter(tag<IndexImpl>{}, data_.value_, pi.p, pi.index, mask_.value_); } @@ -581,7 +581,7 @@ namespace simd_detail { static constexpr unsigned N = simd_traits<ImplTo>::width; using scalar_type = typename simd_traits<ImplTo>::scalar_type; - template <typename ImplFrom, typename = typename std::enable_if<N==simd_traits<ImplFrom>::width>::type> + template <typename ImplFrom, typename = std::enable_if_t<N==simd_traits<ImplFrom>::width>> static simd_impl<ImplTo> cast(const simd_impl<ImplFrom>& v) { return simd_impl<ImplTo>(v); } @@ -595,10 +595,10 @@ namespace simd_detail { struct simd_cast_impl<std::array<V, N>> { template < typename ImplFrom, - typename = typename std::enable_if< + typename = std::enable_if_t< N==simd_traits<ImplFrom>::width && std::is_same<V, typename simd_traits<ImplFrom>::scalar_type>::value - >::type + > > static std::array<V, N> cast(const simd_impl<ImplFrom>& s) { std::array<V, N> a; @@ -654,7 +654,7 @@ To simd_cast(const From& s) { template < typename IndexImpl, typename PtrLike, - typename V = typename std::remove_reference<decltype(*std::declval<PtrLike>())>::type + typename V = std::remove_reference_t<decltype(*std::declval<PtrLike>())> > simd_detail::indirect_expression<IndexImpl, V> indirect( PtrLike p, diff --git a/include/arbor/simple_sampler.hpp b/include/arbor/simple_sampler.hpp index 480f59cd..2814eb25 100644 --- a/include/arbor/simple_sampler.hpp +++ b/include/arbor/simple_sampler.hpp @@ -24,7 +24,7 @@ struct trace_entry { template <typename V> using trace_data = std::vector<trace_entry<V>>; -template <typename V, typename = typename std::enable_if<std::is_trivially_copyable<V>::value>::type> +template <typename V, typename = std::enable_if_t<std::is_trivially_copyable<V>::value>> class simple_sampler { public: explicit simple_sampler(trace_data<V>& trace): trace_(trace) {} diff --git a/include/arbor/simulation.hpp b/include/arbor/simulation.hpp index c7844e93..844380c6 100644 --- a/include/arbor/simulation.hpp +++ b/include/arbor/simulation.hpp @@ -17,7 +17,9 @@ namespace arb { using spike_export_function = std::function<void(const std::vector<spike>&)>; -struct simulation_state; +// simulation_state comprises private implentation for simulation class. +class simulation_state; + class simulation { public: simulation(const recipe& rec, const domain_decomposition& decomp, const distributed_context* ctx); diff --git a/include/arbor/time_sequence.hpp b/include/arbor/time_sequence.hpp index 5b0fb9ef..dff057c5 100644 --- a/include/arbor/time_sequence.hpp +++ b/include/arbor/time_sequence.hpp @@ -32,9 +32,8 @@ public: template < typename Impl, - typename = typename std::enable_if< - !std::is_same<typename std::decay<Impl>::type, - time_seq>::value>::type + typename = std::enable_if_t< + !std::is_same<std::decay_t<Impl>, time_seq>::value> > time_seq(Impl&& impl): impl_(new wrap<Impl>(std::forward<Impl>(impl))) diff --git a/include/arbor/util/any.hpp b/include/arbor/util/any.hpp index 1854f06d..7198f072 100644 --- a/include/arbor/util/any.hpp +++ b/include/arbor/util/any.hpp @@ -38,10 +38,10 @@ public: template < typename T, - typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, any>::value>::type + typename = std::enable_if_t<!std::is_same<std::decay_t<T>, any>::value> > any(T&& other) { - using contained_type = typename std::decay<T>::type; + using contained_type = std::decay_t<T>; static_assert(std::is_copy_constructible<contained_type>::value, "Type of contained object stored in any must satisfy the CopyConstructible requirements."); @@ -60,10 +60,10 @@ public: template < typename T, - typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, any>::value>::type + typename = std::enable_if_t<!std::is_same<std::decay_t<T>, any>::value> > any& operator=(T&& other) { - using contained_type = typename std::decay<T>::type; + using contained_type = std::decay_t<T>; static_assert(std::is_copy_constructible<contained_type>::value, "Type of contained object stored in any must satisfy the CopyConstructible requirements."); @@ -134,8 +134,7 @@ protected: namespace impl { template <typename T> -using any_cast_remove_qual = typename - std::remove_cv<typename std::remove_reference<T>::type>::type; +using any_cast_remove_qual = std::remove_cv_t<std::remove_reference_t<T>>; } // namespace impl diff --git a/include/arbor/util/any_ptr.hpp b/include/arbor/util/any_ptr.hpp index a8a05bc7..2587511b 100644 --- a/include/arbor/util/any_ptr.hpp +++ b/include/arbor/util/any_ptr.hpp @@ -52,7 +52,7 @@ struct any_ptr { type_ptr_ = &typeid(T*); } - template <typename T, typename = typename std::enable_if<std::is_pointer<T>::value>::type> + template <typename T, typename = std::enable_if_t<std::is_pointer<T>::value>> T as() const noexcept { if (std::is_same<T, void*>::value) { return (T)ptr_; diff --git a/include/arbor/util/enumhash.hpp b/include/arbor/util/enumhash.hpp deleted file mode 100644 index e50d7bf8..00000000 --- a/include/arbor/util/enumhash.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include <functional> -#include <type_traits> - -// Work around for C++11 defect #2148: hashing enums should be supported directly by std::hash. -// Fixed in C++14. - -namespace arb { -namespace util { - -struct enum_hash { - template <typename E, typename V = typename std::underlying_type<E>::type> - std::size_t operator()(E e) const noexcept { - return std::hash<V>{}(static_cast<V>(e)); - } -}; - -} // namespace util -} // namespace arb diff --git a/include/arbor/util/make_unique.hpp b/include/arbor/util/make_unique.hpp deleted file mode 100644 index af0b80b0..00000000 --- a/include/arbor/util/make_unique.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include <memory> - -namespace arb { -namespace util { - -// TODO: Remove when migrate to C++14 - -template <typename T, typename... Args> -std::unique_ptr<T> make_unique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args) ...)); -} - -} // namespace util -} // namespace arb - - diff --git a/include/arbor/util/optional.hpp b/include/arbor/util/optional.hpp index 0822ef0b..f36d3b39 100644 --- a/include/arbor/util/optional.hpp +++ b/include/arbor/util/optional.hpp @@ -77,7 +77,7 @@ namespace detail { struct optional_tag {}; template <typename X> - using is_optional = std::is_base_of<optional_tag, typename std::decay<X>::type>; + using is_optional = std::is_base_of<optional_tag, std::decay_t<X>>; template <typename D, typename X> struct wrapped_type_impl { @@ -91,7 +91,7 @@ namespace detail { template <typename X> struct wrapped_type { - using type = typename wrapped_type_impl<typename std::decay<X>::type, X>::type; + using type = typename wrapped_type_impl<std::decay_t<X>, X>::type; }; template <typename X> @@ -169,7 +169,7 @@ namespace detail { // type utilities template <typename T> - using enable_unless_optional_t = typename std::enable_if<!is_optional<T>::value>::type; + using enable_unless_optional_t = std::enable_if_t<!is_optional<T>::value>; // avoid nonnull address warnings when using operator| with e.g. char array constants template <typename T> @@ -251,10 +251,10 @@ struct optional: detail::optional_base<X> { template < typename Y = X, - typename = typename std::enable_if< + typename = std::enable_if_t< std::is_move_assignable<Y>::value && std::is_move_constructible<Y>::value - >::type + > > optional& operator=(optional&& o) { if (set) { diff --git a/include/arbor/util/uninitialized.hpp b/include/arbor/util/uninitialized.hpp index 23455ff1..7752f2c2 100644 --- a/include/arbor/util/uninitialized.hpp +++ b/include/arbor/util/uninitialized.hpp @@ -19,11 +19,11 @@ namespace util { template <typename T> using enable_if_copy_constructible_t = - typename std::enable_if<std::is_copy_constructible<T>::value>::type; + std::enable_if_t<std::is_copy_constructible<T>::value>; template <typename... T> using enable_if_constructible_t = - typename std::enable_if<std::is_constructible<T...>::value>::type; + std::enable_if_t<std::is_constructible<T...>::value>; /* * Maintains storage for a value of type X, with explicit @@ -32,7 +32,7 @@ using enable_if_constructible_t = template <typename X> class uninitialized { private: - typename std::aligned_storage<sizeof(X), alignof(X)>::type data; + std::aligned_storage_t<sizeof(X), alignof(X)> data; public: using pointer = X*; @@ -74,11 +74,11 @@ public: // Apply the one-parameter functor F to the value by reference. template <typename F> - typename std::result_of<F(reference)>::type apply(F&& f) { return f(ref()); } + std::result_of_t<F(reference)> apply(F&& f) { return f(ref()); } // Apply the one-parameter functor F to the value by const reference. template <typename F> - typename std::result_of<F(const_reference)>::type apply(F&& f) const { return f(cref()); } + std::result_of_t<F(const_reference)> apply(F&& f) const { return f(cref()); } }; /* diff --git a/include/arbor/util/unique_any.hpp b/include/arbor/util/unique_any.hpp index cae9edbe..d5b72f6f 100644 --- a/include/arbor/util/unique_any.hpp +++ b/include/arbor/util/unique_any.hpp @@ -56,7 +56,7 @@ public: template < typename T, - typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, unique_any>::value>::type + typename = std::enable_if_t<!std::is_same<std::decay_t<T>, unique_any>::value> > unique_any(T&& other) { state_.reset(new model<contained_type<T>>(std::forward<T>(other))); @@ -69,7 +69,7 @@ public: template < typename T, - typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, unique_any>::value>::type + typename = std::enable_if_t<!std::is_same<std::decay_t<T>, unique_any>::value> > unique_any& operator=(T&& other) { state_.reset(new model<contained_type<T>>(std::forward<T>(other))); @@ -94,7 +94,7 @@ public: private: template <typename T> - using contained_type = typename std::decay<T>::type; + using contained_type = std::decay_t<T>; struct interface { virtual ~interface() = default; diff --git a/lmorpho/lsys_models.cpp b/lmorpho/lsys_models.cpp index 06cd740a..41caf7e1 100644 --- a/lmorpho/lsys_models.cpp +++ b/lmorpho/lsys_models.cpp @@ -1,9 +1,9 @@ -#include <math.hpp> +#include <cmath> #include "lsystem.hpp" #include "lsys_models.hpp" -static constexpr double inf = arb::math::infinity<double>(); +static constexpr double inf = INFINITY; // Predefined parameters for two classes of neurons. Numbers taken primarily // from Ascoli et al. 2001, but some details (soma diameters for example) diff --git a/lmorpho/lsystem.cpp b/lmorpho/lsystem.cpp index feddc70c..e2ceee43 100644 --- a/lmorpho/lsystem.cpp +++ b/lmorpho/lsystem.cpp @@ -5,7 +5,6 @@ #include <vector> #include <arbor/morphology.hpp> - #include "math.hpp" #include "lsystem.hpp" diff --git a/modcc/functionexpander.cpp b/modcc/functionexpander.cpp index 7cbc3545..aedf9f16 100644 --- a/modcc/functionexpander.cpp +++ b/modcc/functionexpander.cpp @@ -1,4 +1,5 @@ #include <iostream> +#include <memory> #include "astmanip.hpp" #include "error.hpp" @@ -18,7 +19,7 @@ expression_ptr insert_unique_local_assignment(expr_list_type& stmts, Expression* expr_list_type lower_function_calls(Expression* e) { - auto v = make_unique<FunctionCallLowerer>(e->scope()); + auto v = std::make_unique<FunctionCallLowerer>(e->scope()); if(auto a=e->is_assignment()) { #ifdef LOGGING diff --git a/modcc/modccutil.hpp b/modcc/modccutil.hpp index 7dd73f19..58dc7d1a 100644 --- a/modcc/modccutil.hpp +++ b/modcc/modccutil.hpp @@ -159,8 +159,3 @@ std::ostream& operator<< (std::ostream& os, std::vector<T> const& V) { return os << "]"; } -template <typename T, typename... Args> -std::unique_ptr<T> make_unique(Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args) ...)); -} - diff --git a/modcc/module.cpp b/modcc/module.cpp index 409845d4..dbabd329 100644 --- a/modcc/module.cpp +++ b/modcc/module.cpp @@ -2,6 +2,7 @@ #include <cassert> #include <fstream> #include <iostream> +#include <memory> #include <set> #include <unordered_set> @@ -312,13 +313,13 @@ bool Module::semantic() { switch(solve_expression->method()) { case solverMethod::cnexp: - solver = make_unique<CnexpSolverVisitor>(); + solver = std::make_unique<CnexpSolverVisitor>(); break; case solverMethod::sparse: - solver = make_unique<SparseSolverVisitor>(); + solver = std::make_unique<SparseSolverVisitor>(); break; case solverMethod::none: - solver = make_unique<DirectSolverVisitor>(); + solver = std::make_unique<DirectSolverVisitor>(); break; } diff --git a/modcc/printer/infoprinter.cpp b/modcc/printer/infoprinter.cpp index cd9f413c..0d64f56a 100644 --- a/modcc/printer/infoprinter.cpp +++ b/modcc/printer/infoprinter.cpp @@ -23,14 +23,14 @@ std::ostream& operator<<(std::ostream& out, const id_field_info& wrap) { const Id& id = wrap.id; out << "{" << quote(id.name()) << ", " - << "spec(spec::" << wrap.kind << ", " << quote(id.unit_string()) << ", " + << "{spec::" << wrap.kind << ", " << quote(id.unit_string()) << ", " << (id.has_value()? id.value: "0"); if (id.has_range()) { out << ", " << id.range.first.spelling << "," << id.range.second.spelling; } - out << ")}"; + out << "}}"; return out; } diff --git a/modcc/token.hpp b/modcc/token.hpp index 3fd5bb0b..97667c2e 100644 --- a/modcc/token.hpp +++ b/modcc/token.hpp @@ -84,16 +84,6 @@ enum class tok { reserved, // placeholder for generating keyword lookup }; -namespace std { - // note: necessary before C++14 (refer: lwg dr#2148). - template <> - struct hash<tok> { - std::size_t operator()(const tok& x) const { - return std::hash<int>()(static_cast<int>(x)); - } - }; -} - // what is in a token? // tok indicating type of token // information about its location diff --git a/test/unit-distributed/distributed_listener.hpp b/test/unit-distributed/distributed_listener.hpp index 6c61f8b4..acf3c1a8 100644 --- a/test/unit-distributed/distributed_listener.hpp +++ b/test/unit-distributed/distributed_listener.hpp @@ -60,6 +60,9 @@ private: printer(std::string base_name, int rank); }; + template <typename T> + friend printer& operator<<(printer&, const T&); + const arb::distributed_context* context_; int rank_; int size_; diff --git a/test/unit-modcc/test_printers.cpp b/test/unit-modcc/test_printers.cpp index 8ba6a2b8..8dbbedaf 100644 --- a/test/unit-modcc/test_printers.cpp +++ b/test/unit-modcc/test_printers.cpp @@ -1,3 +1,4 @@ +#include <memory> #include <regex> #include <string> #include <sstream> @@ -6,6 +7,7 @@ #include "printer/cexpr_emit.hpp" #include "printer/cprinter.hpp" +#include "printer/cudaprinter.hpp" #include "expression.hpp" #include "symdiff.hpp" @@ -89,7 +91,7 @@ TEST(scalar_printer, statement) { { SCOPED_TRACE("CPrinter"); std::stringstream out; - auto printer = make_unique<CPrinter>(out); + auto printer = std::make_unique<CPrinter>(out); e->accept(printer.get()); std::string text = out.str(); @@ -97,20 +99,16 @@ TEST(scalar_printer, statement) { EXPECT_EQ(strip(tc.expected), strip(text)); } -#if 0 { - SCOPED_TRACE("CUDAPrinter"); - TextBuffer buf; - auto printer = make_unique<CUDAPrinter>(); - printer->set_buffer(buf); - + SCOPED_TRACE("CudaPrinter"); + std::stringstream out; + auto printer = std::make_unique<CudaPrinter>(out); e->accept(printer.get()); - std::string text = buf.str(); + std::string text = out.str(); verbose_print(e->to_string(), " :--: ", text); EXPECT_EQ(strip(tc.expected), strip(text)); } -#endif } } @@ -150,7 +148,7 @@ TEST(CPrinter, proc_body) { proc->semantic(globals); std::stringstream out; - auto v = make_unique<CPrinter>(out); + auto v = std::make_unique<CPrinter>(out); proc->is_procedure()->body()->accept(v.get()); std::string text = out.str(); diff --git a/test/unit/common.hpp b/test/unit/common.hpp index 7f9b73d9..46e3f5cd 100644 --- a/test/unit/common.hpp +++ b/test/unit/common.hpp @@ -13,15 +13,6 @@ namespace testing { -// String ctor suffix (until C++14!). - -namespace string_literals { - inline std::string operator ""_s(const char* s, std::size_t n) { - return std::string(s, n); - } -} - - // Sentinel for C-style strings, for use with range-related tests. struct null_terminated_t { diff --git a/test/unit/test_algorithms.cpp b/test/unit/test_algorithms.cpp index 7a0e8aa6..8a2aef6d 100644 --- a/test/unit/test_algorithms.cpp +++ b/test/unit/test_algorithms.cpp @@ -780,7 +780,7 @@ TEST(algorithms, binary_find) auto itv = binary_find(vr, 10); auto found = itv!=std::end(vr); EXPECT_TRUE(found); - EXPECT_EQ(std::distance(arb::util::cbegin(v), itv), 1u); + EXPECT_EQ(std::distance(std::cbegin(v), itv), 1u); if (found) { EXPECT_EQ(*itv, 10); } diff --git a/test/unit/test_any.cpp b/test/unit/test_any.cpp index 03dd829a..5085bb1c 100644 --- a/test/unit/test_any.cpp +++ b/test/unit/test_any.cpp @@ -1,3 +1,4 @@ +#include <string> #include <type_traits> #include <typeinfo> @@ -7,8 +8,8 @@ #include "../gtest.h" #include "common.hpp" +using namespace std::string_literals; using namespace arb; -using namespace testing::string_literals; TEST(any, copy_construction) { util::any any_int(2); @@ -74,7 +75,7 @@ TEST(any, type) { using util::any; any anyi(42); - any anys("hello"_s); + any anys("hello"s); any anyv(std::vector<int>{1, 2, 3}); any any0; @@ -140,7 +141,7 @@ TEST(any, any_cast_ptr) { auto ptr_i = util::any_cast<int>(&ai); EXPECT_EQ(*ptr_i, 42); - util::any as("hello"_s); + util::any as("hello"s); auto ptr_s = util::any_cast<std::string>(&as); EXPECT_EQ(*ptr_s, "hello"); @@ -302,7 +303,7 @@ TEST(any, make_any) { // create a string from const char* auto a = make_any<std::string>("hello"); - EXPECT_EQ(any_cast<std::string>(a), "hello"_s); + EXPECT_EQ(any_cast<std::string>(a), "hello"s); } // test that we make_any correctly forwards rvalue arguments to the constructor diff --git a/test/unit/test_compartments.cpp b/test/unit/test_compartments.cpp index 9d5c711f..13196d73 100644 --- a/test/unit/test_compartments.cpp +++ b/test/unit/test_compartments.cpp @@ -92,7 +92,7 @@ TEST(compartments, div_ends) { EXPECT_DOUBLE_EQ(volume_frustrum(l, r2, r1), d.volume()); auto sl = l/2.0; - auto rc = mean(r1, r2); + auto rc = 0.5*(r1+r2); div_compartment expected{ 0, diff --git a/test/unit/test_cycle.cpp b/test/unit/test_cycle.cpp index 6cac18a8..ec935ae1 100644 --- a/test/unit/test_cycle.cpp +++ b/test/unit/test_cycle.cpp @@ -111,8 +111,8 @@ TEST(cycle_iterator, decrement) { TEST(cycle_iterator, carray) { int values[] = { 4, 2, 3 }; - auto cycle_iter = util::make_cyclic_iterator(util::cbegin(values), - util::cend(values)); + auto cycle_iter = util::make_cyclic_iterator(std::cbegin(values), + std::cend(values)); auto values_size = util::size(values); for (auto i = 0u; i < 2*values_size; ++i) { EXPECT_EQ(values[i % values_size], *cycle_iter++); diff --git a/test/unit/test_fvm_layout.cpp b/test/unit/test_fvm_layout.cpp index 2389e9f6..8e3e311d 100644 --- a/test/unit/test_fvm_layout.cpp +++ b/test/unit/test_fvm_layout.cpp @@ -1,3 +1,4 @@ +#include <string> #include <vector> #include <arbor/util/optional.hpp> @@ -13,8 +14,8 @@ #include "common.hpp" #include "../common_cells.hpp" +using namespace std::string_literals; using namespace arb; -using namespace testing::string_literals; using util::make_span; using util::count_along; @@ -272,7 +273,7 @@ TEST(fvm_layout, area) { cable_segment* cable = cells[1].segment(2)->as_cable(); double a = volume(cable)/cable->length(); - EXPECT_FLOAT_EQ(math::pi<double>()*0.8*0.8/4, a); + EXPECT_FLOAT_EQ(math::pi<double>*0.8*0.8/4, a); double h = cable->length()/4; double g = a/h/cable->rL; // [µm·S/cm] @@ -365,11 +366,11 @@ TEST(fvm_layout, synapse_targets) { auto& expsyn_cv = M.mechanisms.at("expsyn").cv; auto& expsyn_target = M.mechanisms.at("expsyn").target; - auto& expsyn_e = value_by_key(M.mechanisms.at("expsyn").param_values, "e"_s).value(); + auto& expsyn_e = value_by_key(M.mechanisms.at("expsyn").param_values, "e"s).value(); auto& exp2syn_cv = M.mechanisms.at("exp2syn").cv; auto& exp2syn_target = M.mechanisms.at("exp2syn").target; - auto& exp2syn_e = value_by_key(M.mechanisms.at("exp2syn").param_values, "e"_s).value(); + auto& exp2syn_e = value_by_key(M.mechanisms.at("exp2syn").param_values, "e"s).value(); EXPECT_TRUE(util::is_sorted(expsyn_cv)); EXPECT_TRUE(util::is_sorted(exp2syn_cv)); @@ -538,8 +539,8 @@ TEST(fvm_layout, density_norm_area) { ASSERT_EQ(1u, M.mechanisms.count("hh")); auto& hh_params = M.mechanisms.at("hh").param_values; - auto& gkbar = value_by_key(hh_params, "gkbar"_s).value(); - auto& gl = value_by_key(hh_params, "gl"_s).value(); + auto& gkbar = value_by_key(hh_params, "gkbar"s).value(); + auto& gl = value_by_key(hh_params, "gl"s).value(); EXPECT_TRUE(testing::seq_almost_eq<double>(expected_gkbar, gkbar)); EXPECT_TRUE(testing::seq_almost_eq<double>(expected_gl, gl)); diff --git a/test/unit/test_fvm_lowered.cpp b/test/unit/test_fvm_lowered.cpp index 56f12249..0bb0461a 100644 --- a/test/unit/test_fvm_lowered.cpp +++ b/test/unit/test_fvm_lowered.cpp @@ -1,3 +1,4 @@ +#include <string> #include <vector> #include "../gtest.h" @@ -28,7 +29,7 @@ #include "../common_cells.hpp" #include "../simple_recipes.hpp" -using namespace testing::string_literals; +using namespace std::string_literals; using backend = arb::multicore::backend; using fvm_cell = arb::fvm_lowered_cell_impl<backend>; @@ -74,18 +75,13 @@ ACCESS_BIND(\ &arb::multicore::mechanism::ion_index_table) -// TODO: C++14 replace use with generic lambda -struct generic_isnan { - template <typename V> - bool operator()(V& v) const { return std::isnan(v); } -} isnan_; - using namespace arb; TEST(fvm_lowered, matrix_init) { - algorithms::generic_is_positive ispos; - algorithms::generic_is_negative isneg; + auto isnan = [](auto v) { return std::isnan(v); }; + auto ispos = [](auto v) { return v>0; }; + auto isneg = [](auto v) { return v<0; }; mc_cell cell = make_cell_ball_and_stick(); @@ -108,9 +104,9 @@ TEST(fvm_lowered, matrix_init) auto n = J.size(); auto& mat = J.state_; - EXPECT_FALSE(util::any_of(util::subrange_view(mat.u, 1, n), isnan_)); - EXPECT_FALSE(util::any_of(mat.d, isnan_)); - EXPECT_FALSE(util::any_of(J.solution(), isnan_)); + EXPECT_FALSE(util::any_of(util::subrange_view(mat.u, 1, n), isnan)); + EXPECT_FALSE(util::any_of(mat.d, isnan)); + EXPECT_FALSE(util::any_of(J.solution(), isnan)); EXPECT_FALSE(util::any_of(util::subrange_view(mat.u, 1, n), ispos)); EXPECT_FALSE(util::any_of(mat.d, isneg)); @@ -301,12 +297,12 @@ TEST(fvm_lowered, derived_mechs) { using fvec = std::vector<fvm_value_type>; fvec tau_values; for (auto& mech: fvcell.*private_mechanisms_ptr) { - EXPECT_EQ("test_kin1"_s, mech->internal_name()); + EXPECT_EQ("test_kin1"s, mech->internal_name()); auto cmech = dynamic_cast<multicore::mechanism*>(mech.get()); ASSERT_TRUE(cmech); - auto opt_tau_ptr = util::value_by_key((cmech->*private_global_table_ptr)(), "tau"_s); + auto opt_tau_ptr = util::value_by_key((cmech->*private_global_table_ptr)(), "tau"s); ASSERT_TRUE(opt_tau_ptr); tau_values.push_back(*opt_tau_ptr.value()); } @@ -416,7 +412,7 @@ TEST(fvm_lowered, weighted_write_ion) { auto test_ca = dynamic_cast<multicore::mechanism*>(find_mechanism(fvcell, "test_ca")); - auto opt_cai_ptr = util::value_by_key((test_ca->*private_field_table_ptr)(), "cai"_s); + auto opt_cai_ptr = util::value_by_key((test_ca->*private_field_table_ptr)(), "cai"s); ASSERT_TRUE(opt_cai_ptr); auto& test_ca_cai = *opt_cai_ptr.value(); diff --git a/test/unit/test_maputil.cpp b/test/unit/test_maputil.cpp index 17e86938..96ebd6d0 100644 --- a/test/unit/test_maputil.cpp +++ b/test/unit/test_maputil.cpp @@ -2,6 +2,7 @@ #include <map> #include <set> +#include <string> #include <unordered_map> #include <unordered_set> #include <vector> @@ -14,7 +15,7 @@ using namespace arb; -using namespace testing::string_literals; +using namespace std::string_literals; using testing::nocopy; using testing::nomove; @@ -163,10 +164,10 @@ TEST(maputil, value_by_key_sequence) { auto r1 = value_by_key(table, 3); EXPECT_TRUE(r1); - EXPECT_EQ("three"_s, r1.value()); + EXPECT_EQ("three"s, r1.value()); EXPECT_TRUE(is_optional_reference(r1)); r1.value() = "four"; - EXPECT_EQ("four"_s, value_by_key(table, 3).value()); + EXPECT_EQ("four"s, value_by_key(table, 3).value()); auto r2 = value_by_key(std::move(table), 1); EXPECT_TRUE(r2); diff --git a/test/unit/test_math.cpp b/test/unit/test_math.cpp index 93e2c457..7d0d777a 100644 --- a/test/unit/test_math.cpp +++ b/test/unit/test_math.cpp @@ -9,8 +9,8 @@ using namespace arb::math; TEST(math, pi) { // check regression against long double literal in implementation - auto pi_ld = pi<long double>(); - auto pi_d = pi<double>(); + auto pi_ld = pi<long double>; + auto pi_d = pi<double>; if (std::numeric_limits<long double>::digits>std::numeric_limits<double>::digits) { EXPECT_NE(0.0, pi_ld-pi_d); @@ -55,11 +55,11 @@ TEST(math, lerp) { TEST(math, frustrum) { // cross check against cone calculation auto cone_area = [](double l, double r) { - return std::hypot(l,r)*r*pi<double>(); + return std::hypot(l,r)*r*pi<double>; }; auto cone_volume = [](double l, double r) { - return pi<double>()*square(r)*l/3.0; + return pi<double>*square(r)*l/3.0; }; EXPECT_DOUBLE_EQ(cone_area(5.0, 1.3), area_frustrum(5.0, 0.0, 1.3)); @@ -81,17 +81,17 @@ TEST(math, frustrum) { TEST(math, infinity) { // check values for float, double, long double - auto finf = infinity<float>(); + auto finf = infinity<float>; EXPECT_TRUE((std::is_same<float, decltype(finf)>::value)); EXPECT_TRUE(std::isinf(finf)); EXPECT_GT(finf, 0.f); - auto dinf = infinity<double>(); + auto dinf = infinity<double>; EXPECT_TRUE((std::is_same<double, decltype(dinf)>::value)); EXPECT_TRUE(std::isinf(dinf)); EXPECT_GT(dinf, 0.0); - auto ldinf = infinity<long double>(); + auto ldinf = infinity<long double>; EXPECT_TRUE((std::is_same<long double, decltype(ldinf)>::value)); EXPECT_TRUE(std::isinf(ldinf)); EXPECT_GT(ldinf, 0.0l); @@ -101,7 +101,7 @@ TEST(math, infinity) { float f; double d; long double ld; - } check = {infinity<>(), infinity<>(), infinity<>()}; + } check = {infinity<>, infinity<>, infinity<>}; EXPECT_EQ(std::numeric_limits<float>::infinity(), check.f); EXPECT_EQ(std::numeric_limits<double>::infinity(), check.d); @@ -130,10 +130,10 @@ TEST(math, signum) { double negzero = std::copysign(0., -1.); EXPECT_EQ(0, signum(negzero)); - EXPECT_EQ(1, signum(infinity<double>())); - EXPECT_EQ(1, signum(infinity<float>())); - EXPECT_EQ(-1, signum(-infinity<double>())); - EXPECT_EQ(-1, signum(-infinity<float>())); + EXPECT_EQ(1, signum(infinity<double>)); + EXPECT_EQ(1, signum(infinity<float>)); + EXPECT_EQ(-1, signum(-infinity<double>)); + EXPECT_EQ(-1, signum(-infinity<float>)); } TEST(math, next_pow2) { @@ -340,7 +340,7 @@ TEST(quaternion, assignop) { } TEST(quaternion, rotate) { - double deg_to_rad = pi<double>()/180.; + double deg_to_rad = pi<double>/180.; double sqrt3o2 = std::sqrt(3.)/2.; double eps = 1e-15; diff --git a/test/unit/test_mc_cell.cpp b/test/unit/test_mc_cell.cpp index 98e1b5e3..67858182 100644 --- a/test/unit/test_mc_cell.cpp +++ b/test/unit/test_mc_cell.cpp @@ -6,6 +6,7 @@ #include "tree.hpp" using namespace arb; +using ::arb::math::pi; TEST(mc_cell, soma) { // test that insertion of a soma works @@ -108,14 +109,14 @@ TEST(mc_cell, multiple_cables) { // volume = 1 // area = 2 auto seg = [](section_kind k) { - return make_segment<cable_segment>( k, 1.0, 1.0, 1./math::pi<double>() ); + return make_segment<cable_segment>( k, 1.0, 1.0, 1./pi<double> ); }; // add a pre-defined segment { mc_cell c; - auto soma_radius = std::pow(3./(4.*math::pi<double>()), 1./3.); + auto soma_radius = std::pow(3./(4.*pi<double>), 1./3.); // cell strucure as follows // left : segment numbering @@ -160,7 +161,7 @@ TEST(mc_cell, multiple_cables) { TEST(mc_cell, unbranched_chain) { mc_cell c; - auto soma_radius = std::pow(3./(4.*math::pi<double>()), 1./3.); + auto soma_radius = std::pow(3./(4.*pi<double>), 1./3.); // Cell strucure that looks like a centipede: i.e. each segment has only one child // @@ -172,8 +173,8 @@ TEST(mc_cell, unbranched_chain) { c.add_soma(soma_radius, {0,0,1}); // hook the dendrite and axons - c.add_cable(0, make_segment<cable_segment>(section_kind::dendrite, 1.0, 1.0, 1./math::pi<double>())); - c.add_cable(1, make_segment<cable_segment>(section_kind::dendrite, 1.0, 1.0, 1./math::pi<double>())); + c.add_cable(0, make_segment<cable_segment>(section_kind::dendrite, 1.0, 1.0, 1./pi<double>)); + c.add_cable(1, make_segment<cable_segment>(section_kind::dendrite, 1.0, 1.0, 1./pi<double>)); EXPECT_EQ(c.num_segments(), 3u); diff --git a/test/unit/test_mechcat.cpp b/test/unit/test_mechcat.cpp index 1c2a04bf..c19418f5 100644 --- a/test/unit/test_mechcat.cpp +++ b/test/unit/test_mechcat.cpp @@ -1,3 +1,5 @@ +#include <string> + #include <arbor/arbexcept.hpp> #include <arbor/fvm_types.hpp> #include <arbor/mechanism.hpp> @@ -6,8 +8,8 @@ #include "common.hpp" +using namespace std::string_literals; using namespace arb; -using namespace testing::string_literals; // Set up a small system of mechanisms and backends for testing, // comprising: @@ -260,7 +262,7 @@ TEST(mechcat, instance) { EXPECT_EQ(typeid(fleeb_bar), typeid(*special_fleeb_bar_mech.get())); EXPECT_EQ(typeid(fleeb_bar), typeid(*fleeb2_bar_mech.get())); - EXPECT_EQ("fleeb"_s, fleeb2_bar_mech->internal_name()); + EXPECT_EQ("fleeb"s, fleeb2_bar_mech->internal_name()); // special_fleeb and fleeb2 (deriving from special_fleeb) have a specialized // implementation: @@ -275,8 +277,8 @@ TEST(mechcat, instance) { EXPECT_EQ(typeid(special_fleeb_foo), typeid(*special_fleeb_foo_mech.get())); EXPECT_EQ(typeid(special_fleeb_foo), typeid(*fleeb2_foo_mech.get())); - EXPECT_EQ("fleeb"_s, fleeb1_foo_mech->internal_name()); - EXPECT_EQ("special fleeb"_s, fleeb2_foo_mech->internal_name()); + EXPECT_EQ("fleeb"s, fleeb1_foo_mech->internal_name()); + EXPECT_EQ("special fleeb"s, fleeb2_foo_mech->internal_name()); } TEST(mechcat, instantiate) { diff --git a/test/unit/test_multi_event_stream.cpp b/test/unit/test_multi_event_stream.cpp index 62d51fb9..d471a7ba 100644 --- a/test/unit/test_multi_event_stream.cpp +++ b/test/unit/test_multi_event_stream.cpp @@ -1,9 +1,9 @@ #include <vector> #include "../gtest.h" -#include <backends/event.hpp> -#include <backends/multicore/multi_event_stream.hpp> -#include <util/rangeutil.hpp> +#include "backends/event.hpp" +#include "backends/multicore/multi_event_stream.hpp" +#include "util/rangeutil.hpp" using namespace arb; @@ -39,8 +39,9 @@ namespace { namespace { // convenience wrapper around marked_events: template <typename MultiEventStream> - auto marked_range(const MultiEventStream& m, unsigned i) - DEDUCED_RETURN_TYPE(util::make_range(m.marked_events().begin_marked(i), m.marked_events().end_marked(i))) + auto marked_range(const MultiEventStream& m, unsigned i) { + return util::make_range(m.marked_events().begin_marked(i), m.marked_events().end_marked(i)); + } } TEST(multi_event_stream, init) { diff --git a/test/unit/test_optional.cpp b/test/unit/test_optional.cpp index 8759ea8d..c14b34de 100644 --- a/test/unit/test_optional.cpp +++ b/test/unit/test_optional.cpp @@ -9,8 +9,8 @@ #include "common.hpp" +using namespace std::string_literals; using namespace arb::util; -using namespace testing::string_literals; TEST(optional, ctors) { optional<int> a, b(3), c = b, d = 4; @@ -173,7 +173,7 @@ TEST(optional, ctor_nocopy) { const optional<nocopy> ccheck(nocopy(1)); EXPECT_TRUE(std::is_rvalue_reference<decltype(std::move(ccheck).value())>::value); - EXPECT_TRUE(std::is_const<std::remove_reference<decltype(std::move(ccheck).value())>::type>::value); + EXPECT_TRUE(std::is_const<std::remove_reference_t<decltype(std::move(ccheck).value())>>::value); } TEST(optional, value_or) { @@ -194,15 +194,15 @@ TEST(optional, value_or) { }; check_conv cc{true}; - optional<std::string> present = "present"_s; + optional<std::string> present = "present"s; optional<std::string> absent; // nullopt auto result = present.value_or(cc); EXPECT_EQ(typeid(std::string), typeid(result)); - EXPECT_EQ("present"_s, result); + EXPECT_EQ("present"s, result); result = absent.value_or(cc); - EXPECT_EQ("true"_s, result); + EXPECT_EQ("true"s, result); // Check move semantics in argument: @@ -242,7 +242,7 @@ TEST(optional, ref_value_or) { const optional<double&> cx = x; auto& ref3 = cx.value_or(b); - EXPECT_TRUE(std::is_const<std::remove_reference<decltype(ref3)>::type>::value); + EXPECT_TRUE(std::is_const<std::remove_reference_t<decltype(ref3)>>::value); EXPECT_EQ(&b, &ref3); } diff --git a/test/unit/test_range.cpp b/test/unit/test_range.cpp index cb0a3c63..12049ba1 100644 --- a/test/unit/test_range.cpp +++ b/test/unit/test_range.cpp @@ -22,9 +22,9 @@ #include "common.hpp" +using namespace std::string_literals; using namespace arb; -using namespace testing::string_literals; using testing::null_terminated; using testing::nocopy; using testing::nomove; @@ -315,7 +315,7 @@ TYPED_TEST_CASE_P(counter_range); TYPED_TEST_P(counter_range, max_size) { using int_type = TypeParam; - using unsigned_int_type = typename std::make_unsigned<int_type>::type; + using unsigned_int_type = std::make_unsigned_t<int_type>; using counter = util::counter<int_type>; auto l = counter{int_type{1}}; @@ -328,8 +328,8 @@ TYPED_TEST_P(counter_range, max_size) { TYPED_TEST_P(counter_range, extreme_size) { using int_type = TypeParam; - using signed_int_type = typename std::make_signed<int_type>::type; - using unsigned_int_type = typename std::make_unsigned<int_type>::type; + using signed_int_type = std::make_signed_t<int_type>; + using unsigned_int_type = std::make_unsigned_t<int_type>; using counter = util::counter<signed_int_type>; auto l = counter{std::numeric_limits<signed_int_type>::min()}; @@ -342,7 +342,7 @@ TYPED_TEST_P(counter_range, extreme_size) { TYPED_TEST_P(counter_range, size) { using int_type = TypeParam; - using signed_int_type = typename std::make_signed<int_type>::type; + using signed_int_type = std::make_signed_t<int_type>; using counter = util::counter<signed_int_type>; auto l = counter{signed_int_type{-3}}; @@ -354,7 +354,7 @@ TYPED_TEST_P(counter_range, size) { TYPED_TEST_P(counter_range, at) { using int_type = TypeParam; - using signed_int_type = typename std::make_signed<int_type>::type; + using signed_int_type = std::make_signed_t<int_type>; using counter = util::counter<signed_int_type>; auto l = counter{signed_int_type{-3}}; @@ -369,7 +369,7 @@ TYPED_TEST_P(counter_range, at) { TYPED_TEST_P(counter_range, iteration) { using int_type = TypeParam; - using signed_int_type = typename std::make_signed<int_type>::type; + using signed_int_type = std::make_signed_t<int_type>; using counter = util::counter<signed_int_type>; auto j = signed_int_type{-3}; @@ -454,11 +454,11 @@ TEST(range, sort) { // simple sort util::sort(util::strict_view(cstr_range)); - EXPECT_EQ("dhowy"_s, cstr); + EXPECT_EQ("dhowy"s, cstr); // reverse sort by transform c to -c util::sort_by(util::strict_view(cstr_range), [](char c) { return -c; }); - EXPECT_EQ("ywohd"_s, cstr); + EXPECT_EQ("ywohd"s, cstr); // stable sort: move capitals to front, numbers to back auto rank = [](char c) { @@ -469,7 +469,7 @@ TEST(range, sort) { auto mixed_range = util::make_range(std::begin(mixed), null_terminated); util::stable_sort_by(util::strict_view(mixed_range), rank); - EXPECT_EQ("HELLOthere54321"_s, mixed); + EXPECT_EQ("HELLOthere54321"s, mixed); // sort with user-provided less comparison function @@ -489,7 +489,7 @@ TEST(range, sum_by) { auto result = util::sum_by(words, prepend_); EXPECT_EQ("_fish_cakes_!", result); - result = util::sum_by(words, prepend_, "tasty"_s); + result = util::sum_by(words, prepend_, "tasty"s); EXPECT_EQ("tasty_fish_cakes_!", result); auto count = util::sum_by(words, [](const std::string &x) { return x.size(); }); @@ -511,10 +511,10 @@ TEST(range, all_of_any_of) { auto pred = [](char c) { return c=='x'? throw c:c<'5'; }; // all - EXPECT_TRUE(util::all_of(""_s, pred)); - EXPECT_TRUE(util::all_of("1234"_s, pred)); - EXPECT_FALSE(util::all_of("12345"_s, pred)); - EXPECT_FALSE(util::all_of("12345x"_s, pred)); + EXPECT_TRUE(util::all_of(""s, pred)); + EXPECT_TRUE(util::all_of("1234"s, pred)); + EXPECT_FALSE(util::all_of("12345"s, pred)); + EXPECT_FALSE(util::all_of("12345x"s, pred)); EXPECT_TRUE(util::all_of(cstr(""), pred)); EXPECT_TRUE(util::all_of(cstr("1234"), pred)); @@ -522,10 +522,10 @@ TEST(range, all_of_any_of) { EXPECT_FALSE(util::all_of(cstr("12345x"), pred)); // any - EXPECT_FALSE(util::any_of(""_s, pred)); - EXPECT_FALSE(util::any_of("8765"_s, pred)); - EXPECT_TRUE(util::any_of("87654"_s, pred)); - EXPECT_TRUE(util::any_of("87654x"_s, pred)); + EXPECT_FALSE(util::any_of(""s, pred)); + EXPECT_FALSE(util::any_of("8765"s, pred)); + EXPECT_TRUE(util::any_of("87654"s, pred)); + EXPECT_TRUE(util::any_of("87654x"s, pred)); EXPECT_FALSE(util::any_of(cstr(""), pred)); EXPECT_FALSE(util::any_of(cstr("8765"), pred)); @@ -549,10 +549,10 @@ TEST(range, is_sorted) { EXPECT_FALSE(util::is_sorted(ivec({1,2,2,1,4}))); EXPECT_TRUE(util::is_sorted(cstr("abccd"))); - EXPECT_TRUE(util::is_sorted("abccd"_s)); + EXPECT_TRUE(util::is_sorted("abccd"s)); EXPECT_FALSE(util::is_sorted(cstr("hello"))); - EXPECT_FALSE(util::is_sorted("hello"_s)); + EXPECT_FALSE(util::is_sorted("hello"s)); } template <typename C> @@ -659,7 +659,7 @@ TEST(range, reverse) { std::string rev; util::assign(rev, util::reverse_view(cstr("hello"))); - EXPECT_EQ("olleh"_s, rev); + EXPECT_EQ("olleh"s, rev); } diff --git a/test/unit/test_segment.cpp b/test/unit/test_segment.cpp index ed6022e8..de33809d 100644 --- a/test/unit/test_segment.cpp +++ b/test/unit/test_segment.cpp @@ -9,8 +9,7 @@ using namespace arb; TEST(mc_segment, kinfs) { - using namespace arb; - using arb::math::pi; + using ::arb::math::pi; { auto s = make_segment<soma_segment>(1.0); @@ -22,7 +21,7 @@ TEST(mc_segment, kinfs) { EXPECT_EQ(s->kind(), section_kind::soma); } - double length = 1./pi<double>(); + double length = 1./pi<double>; double radius = 1.; // single cylindrical frustrum diff --git a/test/unit/test_simd.cpp b/test/unit/test_simd.cpp index c266b2b5..0aea5359 100644 --- a/test/unit/test_simd.cpp +++ b/test/unit/test_simd.cpp @@ -21,12 +21,12 @@ namespace { // * other integral type => uniform_int_distribution, default interval [L, U] // such that L^2+L and U^2+U fit within the integer range. - template <typename V, typename = typename std::enable_if<std::is_floating_point<V>::value>::type> + template <typename V, typename = std::enable_if_t<std::is_floating_point<V>::value>> std::uniform_real_distribution<V> make_udist(V lb = -1., V ub = 1.) { return std::uniform_real_distribution<V>(lb, ub); } - template <typename V, typename = typename std::enable_if<std::is_integral<V>::value && !std::is_same<V, bool>::value>::type> + template <typename V, typename = std::enable_if_t<std::is_integral<V>::value && !std::is_same<V, bool>::value>> std::uniform_int_distribution<V> make_udist( V lb = std::numeric_limits<V>::lowest() / (2 << std::numeric_limits<V>::digits/2), V ub = std::numeric_limits<V>::max() >> (1+std::numeric_limits<V>::digits/2)) @@ -34,14 +34,14 @@ namespace { return std::uniform_int_distribution<V>(lb, ub); } - template <typename V, typename = typename std::enable_if<std::is_same<V, bool>::value>::type> + template <typename V, typename = std::enable_if_t<std::is_same<V, bool>::value>> std::uniform_int_distribution<> make_udist(V lb = 0, V ub = 1) { return std::uniform_int_distribution<>(0, 1); } template <typename Seq, typename Rng> void fill_random(Seq&& seq, Rng& rng) { - using V = typename std::decay<decltype(*std::begin(seq))>::type; + using V = std::decay_t<decltype(*std::begin(seq))>; auto u = make_udist<V>(); for (auto& x: seq) { x = u(rng); } @@ -49,13 +49,13 @@ namespace { template <typename Seq, typename Rng, typename B1, typename B2> void fill_random(Seq&& seq, Rng& rng, B1 lb, B2 ub) { - using V = typename std::decay<decltype(*std::begin(seq))>::type; + using V = std::decay_t<decltype(*std::begin(seq))>; auto u = make_udist<V>(lb, ub); for (auto& x: seq) { x = u(rng); } } - template <typename Simd, typename Rng, typename B1, typename B2, typename = typename std::enable_if<is_simd<Simd>::value>::type> + template <typename Simd, typename Rng, typename B1, typename B2, typename = std::enable_if_t<is_simd<Simd>::value>> void fill_random(Simd& s, Rng& rng, B1 lb, B2 ub) { using V = typename Simd::scalar_type; constexpr unsigned N = Simd::width; @@ -65,7 +65,7 @@ namespace { s.copy_from(v); } - template <typename Simd, typename Rng, typename = typename std::enable_if<is_simd<Simd>::value>::type> + template <typename Simd, typename Rng, typename = std::enable_if_t<is_simd<Simd>::value>> void fill_random(Simd& s, Rng& rng) { using V = typename Simd::scalar_type; constexpr unsigned N = Simd::width; @@ -1064,7 +1064,8 @@ TYPED_TEST_P(simd_indirect, add_and_subtract) { template <typename X> bool unique_elements(const X& xs) { using std::begin; - std::unordered_set<typename std::decay<decltype(*begin(xs))>::type> set; +// WOOPWOOP + std::unordered_set<std::decay_t<decltype(*begin(xs))>> set; for (auto& x: xs) { if (!set.insert(x).second) return false; } diff --git a/test/unit/test_strprintf.cpp b/test/unit/test_strprintf.cpp index 3bb01dd8..08cade7d 100644 --- a/test/unit/test_strprintf.cpp +++ b/test/unit/test_strprintf.cpp @@ -7,8 +7,8 @@ #include "../gtest.h" #include "common.hpp" +using namespace std::string_literals; using namespace arb::util; -using namespace testing::string_literals; TEST(strprintf, simple) { char buf[200]; @@ -60,6 +60,6 @@ TEST(strprintf, wrappers) { EXPECT_EQ(std::string(buf), strprintf("sptr %p", sptr)); - EXPECT_EQ("fish"_s, strprintf("fi%s", "sh"_s)); + EXPECT_EQ("fish"s, strprintf("fi%s", "sh"s)); } diff --git a/test/unit/test_unique_any.cpp b/test/unit/test_unique_any.cpp index 038d4341..02612a09 100644 --- a/test/unit/test_unique_any.cpp +++ b/test/unit/test_unique_any.cpp @@ -9,7 +9,6 @@ #include "common.hpp" using namespace arb; -using namespace testing::string_literals; TEST(unique_any, copy_construction) { using util::unique_any; diff --git a/test/unit/test_vector.cpp b/test/unit/test_vector.cpp index 76f9781b..1176555f 100644 --- a/test/unit/test_vector.cpp +++ b/test/unit/test_vector.cpp @@ -31,7 +31,7 @@ TEST(vector, make_view_stdvector) { TEST(vector, make_host_stdvector) { std::vector<int> stdvec(10); auto host_vec = memory::on_host(stdvec); - using target_type = std::decay<decltype(host_vec)>::type; + using target_type = std::decay_t<decltype(host_vec)>; EXPECT_EQ(host_vec.size(), stdvec.size()); EXPECT_EQ(host_vec.data(), stdvec.data()); EXPECT_TRUE(memory::util::is_on_host<target_type>()); @@ -44,7 +44,7 @@ TEST(vector, make_host_hostvector) { memory::host_vector<int> vec(10); { // test from host_vector auto host_view = memory::on_host(vec); - using target_type = std::decay<decltype(host_view)>::type; + using target_type = std::decay_t<decltype(host_view)>; EXPECT_EQ(host_view.size(), vec.size()); EXPECT_EQ(host_view.data(), vec.data()); EXPECT_TRUE(memory::util::is_on_host<target_type>()); @@ -54,7 +54,7 @@ TEST(vector, make_host_hostvector) { { // test from view auto view = memory::make_view(vec); auto host_view = memory::on_host(view); - using target_type = std::decay<decltype(host_view)>::type; + using target_type = std::decay_t<decltype(host_view)>; EXPECT_EQ(host_view.size(), view.size()); EXPECT_EQ(host_view.data(), view.data()); EXPECT_TRUE(memory::util::is_on_host<target_type>()); diff --git a/test/unit/test_vector.cu b/test/unit/test_vector.cu index f3562f02..5a195e48 100644 --- a/test/unit/test_vector.cu +++ b/test/unit/test_vector.cu @@ -16,7 +16,7 @@ using namespace arb; TEST(vector, make_gpu_stdvector) { std::vector<int> stdvec(10); auto gpu_vec = memory::on_gpu(stdvec); - using target_type = std::decay<decltype(gpu_vec)>::type; + using target_type = std::decay_t<decltype(gpu_vec)>; EXPECT_EQ(gpu_vec.size(), stdvec.size()); EXPECT_NE(gpu_vec.data(), stdvec.data()); EXPECT_TRUE(memory::util::is_on_gpu<target_type>()); @@ -29,7 +29,7 @@ TEST(vector, make_gpu_stdvector) { TEST(vector, make_host_devicevector) { memory::device_vector<int> dvec(10); auto host_vec = memory::on_host(dvec); - using target_type = std::decay<decltype(host_vec)>::type; + using target_type = std::decay_t<decltype(host_vec)>; EXPECT_EQ(host_vec.size(), dvec.size()); EXPECT_NE(host_vec.data(), dvec.data()); EXPECT_TRUE(memory::util::is_on_host<target_type>()); @@ -43,7 +43,7 @@ TEST(vector, make_host_devicevector) { TEST(vector, make_gpu_devicevector) { memory::device_vector<int> dvec(10); auto view = memory::on_gpu(dvec); - using target_type = std::decay<decltype(view)>::type; + using target_type = std::decay_t<decltype(view)>; EXPECT_EQ(view.size(), dvec.size()); EXPECT_EQ(view.data(), dvec.data()); EXPECT_TRUE(memory::util::is_on_gpu<target_type>()); diff --git a/test/validation/trace_analysis.hpp b/test/validation/trace_analysis.hpp index 167952cb..e6ff032d 100644 --- a/test/validation/trace_analysis.hpp +++ b/test/validation/trace_analysis.hpp @@ -1,5 +1,6 @@ #pragma once +#include <cfloat> #include <vector> #include "../gtest.h" @@ -7,9 +8,6 @@ #include <arbor/simple_sampler.hpp> #include <arbor/util/optional.hpp> -#include "math.hpp" -#include "util/path.hpp" -#include "util/deduce_return.hpp" #include "util/rangeutil.hpp" namespace arb { @@ -18,26 +16,15 @@ namespace arb { // Extract time or value data from trace. -namespace impl { - // NB: work-around for lack of function return type deduction - // in C++11; can't use lambda within DEDUCED_RETURN_TYPE. - - template <typename V> - inline float time(const trace_entry<V>& x) { return x.t; } - - template <typename V> - inline const V& value(const trace_entry<V>& x) { return x.v; } -} - template <typename V> -inline auto times(const trace_data<V>& trace) DEDUCED_RETURN_TYPE( - util::transform_view(trace, impl::time<V>) -) +inline auto times(const trace_data<V>& trace) { + return util::transform_view(trace, [](auto& x) { return x.t; }); +} template <typename V> -inline auto values(const trace_data<V>& trace) DEDUCED_RETURN_TYPE( - util::transform_view(trace, impl::value<V>) -) +inline auto values(const trace_data<V>& trace) { + return util::transform_view(trace, [](auto& x) { return x.v; }); +} // Compute max |v_i - f(t_i)| where (t, v) is the // first trace `u` and f is the piece-wise linear interpolant @@ -93,7 +80,7 @@ void assert_convergence(const ConvEntrySeq& cs) { if (util::empty(cs)) return; auto tbound = [](trace_peak p) { return std::abs(p.t)+p.t_err; }; - float peak_dt_bound = math::infinity<>(); + float peak_dt_bound = INFINITY; for (auto pi = std::begin(cs); std::next(pi)!=std::end(cs); ++pi) { const auto& p = *pi; diff --git a/test/validation/validate_kinetic.cpp b/test/validation/validate_kinetic.cpp index a1d78a56..dd335976 100644 --- a/test/validation/validate_kinetic.cpp +++ b/test/validation/validate_kinetic.cpp @@ -37,7 +37,8 @@ void run_kinetic_dt( cable1d_recipe rec{c}; rec.add_probe(0, 0, probe); - probe_label plabels[1] = {"soma.mid", {0u, 0u}}; + + probe_label plabels[1] = {{"soma.mid", {0u, 0u}}}; meta["sim"] = "arbor"; meta["backend_kind"] = util::to_string(backend); diff --git a/test/validation/validate_soma.cpp b/test/validation/validate_soma.cpp index 27458680..90534c4c 100644 --- a/test/validation/validate_soma.cpp +++ b/test/validation/validate_soma.cpp @@ -30,7 +30,7 @@ void validate_soma(backend_kind backend) { cable1d_recipe rec{c}; rec.add_probe(0, 0, cell_probe_address{{0, 0.5}, cell_probe_address::membrane_voltage}); - probe_label plabels[1] = {"soma.mid", {0u, 0u}}; + probe_label plabels[1] = {{"soma.mid", {0u, 0u}}}; distributed_context context; hw::node_info nd(1, backend==backend_kind::gpu? 1: 0); -- GitLab