diff --git a/include/boost/histogram/algorithm/reduce.hpp b/include/boost/histogram/algorithm/reduce.hpp index f3a025aa..a9d6c024 100644 --- a/include/boost/histogram/algorithm/reduce.hpp +++ b/include/boost/histogram/algorithm/reduce.hpp @@ -10,10 +10,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -21,6 +19,7 @@ #include #include #include +#include namespace boost { namespace histogram { @@ -250,10 +249,9 @@ decltype(auto) reduce(const Histogram& hist, const Iterable& options) { o.end -= (o.end - o.begin) % o.merge; aout = A(ain, o.begin, o.end, o.merge); }, - [](auto&&, const auto& ain) { - using A = std::decay_t; - BOOST_THROW_EXCEPTION(std::invalid_argument( - detail::cat(detail::type_name(), " is not reducible"))); + [iaxis](auto&&, const auto&) { + BOOST_THROW_EXCEPTION(std::invalid_argument("axis " + std::to_string(iaxis) + + " is not reducible")); }, axis::get(detail::axis_get(axes, iaxis)), a); } else { diff --git a/include/boost/histogram/axis/ostream.hpp b/include/boost/histogram/axis/ostream.hpp index f9de9010..ca307a59 100644 --- a/include/boost/histogram/axis/ostream.hpp +++ b/include/boost/histogram/axis/ostream.hpp @@ -11,13 +11,13 @@ #include #include -#include #include #include #include #include #include #include +#include #include #include diff --git a/include/boost/histogram/axis/traits.hpp b/include/boost/histogram/axis/traits.hpp index 8502c518..62a8afe9 100644 --- a/include/boost/histogram/axis/traits.hpp +++ b/include/boost/histogram/axis/traits.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -22,6 +21,7 @@ #include #include #include +#include #include namespace boost { @@ -56,7 +56,7 @@ double value_method_switch_impl1(std::false_type, I&&, D&&, const A&) { // comma trick to make all compilers happy; some would complain about // unreachable code after the throw, others about a missing return return BOOST_THROW_EXCEPTION( - std::runtime_error(cat(type_name(), " has no value method"))), + std::runtime_error(type_name() + " has no value method")), double{}; } diff --git a/include/boost/histogram/axis/variable.hpp b/include/boost/histogram/axis/variable.hpp index 46feb0ad..53af4416 100644 --- a/include/boost/histogram/axis/variable.hpp +++ b/include/boost/histogram/axis/variable.hpp @@ -83,12 +83,14 @@ public: vec_.reserve(std::distance(begin, end)); vec_.emplace_back(*begin++); + bool strictly_ascending = true; while (begin != end) { - if (*begin <= vec_.back()) - BOOST_THROW_EXCEPTION( - std::invalid_argument("input sequence must be strictly ascending")); + if (*begin <= vec_.back()) strictly_ascending = false; vec_.emplace_back(*begin++); } + if (!strictly_ascending) + BOOST_THROW_EXCEPTION( + std::invalid_argument("input sequence must be strictly ascending")); } /** Construct variable axis from iterable range of bin edges. diff --git a/include/boost/histogram/axis/variant.hpp b/include/boost/histogram/axis/variant.hpp index 1a3db038..949ec5c6 100644 --- a/include/boost/histogram/axis/variant.hpp +++ b/include/boost/histogram/axis/variant.hpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,6 @@ #include // mp_first #include #include -#include #include #include #include @@ -74,9 +72,9 @@ public: detail::static_if>( [this](const auto& u) { this->operator=(u); }, [](const auto&) { - BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat( - detail::type_name(), " is not convertible to a bounded type of ", - detail::type_name()))); + BOOST_THROW_EXCEPTION(std::runtime_error( + detail::type_name() + " is not convertible to a bounded type of " + + detail::type_name())); }, u); }, @@ -109,11 +107,11 @@ public: [](const auto& a) -> const metadata_type& { return traits::metadata(a); }, [](const auto&) -> const metadata_type& { BOOST_THROW_EXCEPTION(std::runtime_error( - detail::cat("cannot return metadata of type ", detail::type_name(), - " through axis::variant interface which uses type ", - detail::type_name(), - "; use boost::histogram::axis::get to obtain a reference " - "of this axis type"))); + "cannot return metadata of type " + detail::type_name() + + " through axis::variant interface which uses type " + + detail::type_name() + + "; use boost::histogram::axis::get to obtain a reference " + "of this axis type")); }, a); }, @@ -130,11 +128,11 @@ public: [](auto& a) -> metadata_type& { return traits::metadata(a); }, [](auto&) -> metadata_type& { BOOST_THROW_EXCEPTION(std::runtime_error( - detail::cat("cannot return metadata of type ", detail::type_name(), - " through axis::variant interface which uses type ", - detail::type_name(), - "; use boost::histogram::axis::get to obtain a reference " - "of this axis type"))); + "cannot return metadata of type " + detail::type_name() + + " through axis::variant interface which uses type " + + detail::type_name() + + "; use boost::histogram::axis::get to obtain a reference " + "of this axis type")); }, a); }, diff --git a/include/boost/histogram/detail/axes.hpp b/include/boost/histogram/detail/axes.hpp index 018e648c..e973b416 100644 --- a/include/boost/histogram/detail/axes.hpp +++ b/include/boost/histogram/detail/axes.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -57,9 +58,10 @@ template void throw_if_axes_is_too_large(const T& axes) { if (axes_rank(axes) > BOOST_HISTOGRAM_DETAIL_AXES_LIMIT) BOOST_THROW_EXCEPTION( - std::invalid_argument(cat("length of axis vector exceeds internal buffers, " - "recompile with -DBOOST_HISTOGRAM_DETAIL_AXES_LIMIT=", - axes_rank(axes), " to increase internal buffers"))); + std::invalid_argument("length of axis vector exceeds internal buffers, " + "recompile with " + "-DBOOST_HISTOGRAM_DETAIL_AXES_LIMIT= " + "to increase internal buffers")); } // tuple is never too large because internal buffers adapt to size of tuple diff --git a/include/boost/histogram/detail/cat.hpp b/include/boost/histogram/detail/cat.hpp deleted file mode 100644 index f977c014..00000000 --- a/include/boost/histogram/detail/cat.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015-2017 Hans Dembinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_HISTOGRAM_DETAIL_CAT_HPP -#define BOOST_HISTOGRAM_DETAIL_CAT_HPP - -#include -#include - -namespace boost { -namespace histogram { -namespace detail { -BOOST_ATTRIBUTE_UNUSED inline void cat_impl(std::ostringstream&) {} - -template -void cat_impl(std::ostringstream& os, const T& t, const Ts&... ts) { - os << t; - cat_impl(os, ts...); -} - -template -std::string cat(const Ts&... args) { - std::ostringstream os; - cat_impl(os, args...); - return os.str(); -} -} // namespace detail -} // namespace histogram -} // namespace boost - -#endif diff --git a/include/boost/histogram/detail/try_cast.hpp b/include/boost/histogram/detail/try_cast.hpp index 249f4e03..1e8a7d27 100644 --- a/include/boost/histogram/detail/try_cast.hpp +++ b/include/boost/histogram/detail/try_cast.hpp @@ -9,11 +9,11 @@ #include #include -#include #include #include #include #include +#include #include namespace boost { @@ -21,7 +21,7 @@ namespace histogram { namespace detail { template BOOST_NORETURN T try_cast_impl(mp11::mp_int<0>, U&&) { - BOOST_THROW_EXCEPTION(E(cat("cannot cast ", type_name(), " to ", type_name()))); + BOOST_THROW_EXCEPTION(E("cannot cast " + type_name() + " to " + type_name())); } template diff --git a/include/boost/histogram/detail/type_name.hpp b/include/boost/histogram/detail/type_name.hpp index 25950bca..bea8f88a 100644 --- a/include/boost/histogram/detail/type_name.hpp +++ b/include/boost/histogram/detail/type_name.hpp @@ -9,7 +9,6 @@ #include #include -#include #include namespace boost { @@ -17,31 +16,28 @@ namespace histogram { namespace detail { template -std::ostream& type_name_impl(std::ostream& os, boost::type) { - os << boost::core::demangled_name(BOOST_CORE_TYPEID(T)); - return os; +std::string type_name_impl(boost::type) { + return boost::core::demangled_name(BOOST_CORE_TYPEID(T)); } template -std::ostream& type_name_impl(std::ostream& os, boost::type) { - return type_name_impl(os, boost::type{}) << " const"; +std::string type_name_impl(boost::type) { + return type_name_impl(boost::type{}) + " const"; } template -std::ostream& type_name_impl(std::ostream& os, boost::type) { - return type_name_impl(os, boost::type{}) << "&"; +std::string type_name_impl(boost::type) { + return type_name_impl(boost::type{}) + " &"; } template -std::ostream& type_name_impl(std::ostream& os, boost::type) { - return type_name_impl(os, boost::type{}) << "&&"; +std::string type_name_impl(boost::type) { + return type_name_impl(boost::type{}) + " &&"; } template std::string type_name() { - std::ostringstream os; - type_name_impl(os, boost::type{}); - return os.str(); + return type_name_impl(boost::type{}); } } // namespace detail diff --git a/include/boost/histogram/storage_adaptor.hpp b/include/boost/histogram/storage_adaptor.hpp index e4c849bc..b704526f 100644 --- a/include/boost/histogram/storage_adaptor.hpp +++ b/include/boost/histogram/storage_adaptor.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -90,20 +89,19 @@ struct array_impl : T { template > array_impl& operator=(const U& u) { + if (u.size() > T::max_size()) // for std::arra + BOOST_THROW_EXCEPTION(std::length_error("argument size exceeds maximum capacity")); size_ = u.size(); - if (size_ > T::max_size()) // for std::array - BOOST_THROW_EXCEPTION(std::length_error( - detail::cat("size ", size_, " exceeds maximum capacity ", T::max_size()))); - auto it = T::begin(); - for (auto&& x : u) *it++ = x; + using std::begin; + using std::end; + std::copy(begin(u), end(u), T::begin()); return *this; } void reset(std::size_t n) { using value_type = typename T::value_type; if (n > T::max_size()) // for std::array - BOOST_THROW_EXCEPTION(std::length_error( - detail::cat("size ", n, " exceeds maximum capacity ", T::max_size()))); + BOOST_THROW_EXCEPTION(std::length_error("argument size exceeds maximum capacity")); std::fill_n(T::begin(), n, value_type()); size_ = n; } diff --git a/test/axis_category_test.cpp b/test/axis_category_test.cpp index 11c9db90..5afe477c 100644 --- a/test/axis_category_test.cpp +++ b/test/axis_category_test.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -17,10 +16,11 @@ #include "std_ostream.hpp" #include "throw_exception.hpp" #include "utility_axis.hpp" - -using namespace boost::histogram; +#include "utility_str.hpp" int main() { + using namespace boost::histogram; + BOOST_TEST(std::is_nothrow_move_constructible>::value); BOOST_TEST(std::is_nothrow_move_constructible>::value); BOOST_TEST(std::is_nothrow_move_assignable>::value); @@ -69,7 +69,7 @@ int main() { BOOST_TEST_EQ(a.value(2), C); BOOST_TEST_THROWS(a.value(3), std::out_of_range); - BOOST_TEST_EQ(detail::cat(a), + BOOST_TEST_EQ(str(a), "category(\"A\", \"B\", \"C\", metadata=\"bar\", options=overflow)"); } @@ -131,7 +131,7 @@ int main() { BOOST_TEST_EQ(a.update(10), std::make_pair(2, 0)); BOOST_TEST_EQ(a.size(), 3); - BOOST_TEST_EQ(detail::cat(a), "category(5, 1, 10, options=growth)"); + BOOST_TEST_EQ(str(a), "category(5, 1, 10, options=growth)"); } // iterators diff --git a/test/axis_integer_test.cpp b/test/axis_integer_test.cpp index 10c6b68f..d3556f41 100644 --- a/test/axis_integer_test.cpp +++ b/test/axis_integer_test.cpp @@ -7,16 +7,17 @@ #include #include #include -#include #include +#include #include #include "std_ostream.hpp" #include "throw_exception.hpp" #include "utility_axis.hpp" - -using namespace boost::histogram; +#include "utility_str.hpp" int main() { + using namespace boost::histogram; + BOOST_TEST(std::is_nothrow_move_assignable>::value); BOOST_TEST(std::is_nothrow_move_constructible>::value); @@ -44,7 +45,7 @@ int main() { BOOST_TEST_EQ(a.index(10), 3); BOOST_TEST_EQ(a.index(std::numeric_limits::quiet_NaN()), 3); - BOOST_TEST_EQ(detail::cat(a), + BOOST_TEST_EQ(str(a), "integer(-1, 2, metadata=\"bar\", options=underflow | overflow)"); axis::integer b; @@ -72,7 +73,7 @@ int main() { BOOST_TEST_EQ(a.index(2), 3); BOOST_TEST_EQ(a.index(10), 3); - BOOST_TEST_EQ(detail::cat(a), "integer(-1, 2, options=underflow | overflow)"); + BOOST_TEST_EQ(str(a), "integer(-1, 2, options=underflow | overflow)"); } // axis::integer int,circular @@ -89,7 +90,7 @@ int main() { BOOST_TEST_EQ(a.index(1), 0); BOOST_TEST_EQ(a.index(2), 1); - BOOST_TEST_EQ(detail::cat(a), "integer(-1, 1, options=circular)"); + BOOST_TEST_EQ(str(a), "integer(-1, 1, options=circular)"); } // axis::integer double,circular diff --git a/test/axis_regular_test.cpp b/test/axis_regular_test.cpp index 4f52c981..5d3e111c 100644 --- a/test/axis_regular_test.cpp +++ b/test/axis_regular_test.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -15,12 +14,13 @@ #include "std_ostream.hpp" #include "throw_exception.hpp" #include "utility_axis.hpp" - -using namespace boost::histogram; -namespace tr = axis::transform; -using def = use_default; +#include "utility_str.hpp" int main() { + using namespace boost::histogram; + using def = use_default; + namespace tr = axis::transform; + BOOST_TEST(std::is_nothrow_move_assignable>::value); BOOST_TEST(std::is_nothrow_move_constructible>::value); @@ -73,7 +73,7 @@ int main() { BOOST_TEST_EQ(a.index(std::numeric_limits::infinity()), 4); BOOST_TEST_EQ(a.index(std::numeric_limits::quiet_NaN()), 4); - BOOST_TEST_EQ(detail::cat(a), + BOOST_TEST_EQ(str(a), "regular(4, -2, 2, metadata=\"bar\", options=underflow | overflow)"); } @@ -116,7 +116,7 @@ int main() { BOOST_TEST_THROWS((axis::regular{2, -1, 0}), std::invalid_argument); - BOOST_TEST_EQ(detail::cat(a), "regular_log(2, 1, 100, options=underflow | overflow)"); + BOOST_TEST_EQ(str(a), "regular_log(2, 1, 100, options=underflow | overflow)"); } // with sqrt transform @@ -138,7 +138,7 @@ int main() { BOOST_TEST_EQ(a.index(100), 2); BOOST_TEST_EQ(a.index(std::numeric_limits::infinity()), 2); - BOOST_TEST_EQ(detail::cat(a), "regular_sqrt(2, 0, 4, options=underflow | overflow)"); + BOOST_TEST_EQ(str(a), "regular_sqrt(2, 0, 4, options=underflow | overflow)"); } // with pow transform @@ -160,7 +160,7 @@ int main() { BOOST_TEST_EQ(a.index(100), 2); BOOST_TEST_EQ(a.index(std::numeric_limits::infinity()), 2); - BOOST_TEST_EQ(detail::cat(a), + BOOST_TEST_EQ(str(a), "regular_pow(2, 0, 4, options=underflow | overflow, power=0.5)"); } @@ -244,7 +244,7 @@ int main() { // null_type streamable { auto a = axis::regular(2, 0, 1); - BOOST_TEST_EQ(detail::cat(a), "regular(2, 0, 1, options=underflow | overflow)"); + BOOST_TEST_EQ(str(a), "regular(2, 0, 1, options=underflow | overflow)"); } // shrink and rebin diff --git a/test/axis_variable_test.cpp b/test/axis_variable_test.cpp index 97eb0b39..cb27a093 100644 --- a/test/axis_variable_test.cpp +++ b/test/axis_variable_test.cpp @@ -7,14 +7,15 @@ #include #include #include -#include #include +#include #include #include #include "is_close.hpp" #include "std_ostream.hpp" #include "throw_exception.hpp" #include "utility_axis.hpp" +#include "utility_str.hpp" using namespace boost::histogram; @@ -24,9 +25,9 @@ int main() { // bad_ctors { - auto empty = std::vector(0); - BOOST_TEST_THROWS((axis::variable<>(empty)), std::invalid_argument); + BOOST_TEST_THROWS(axis::variable<>(std::vector{}), std::invalid_argument); BOOST_TEST_THROWS(axis::variable<>({1.0}), std::invalid_argument); + BOOST_TEST_THROWS(axis::variable<>({1.0, 1.0}), std::invalid_argument); BOOST_TEST_THROWS(axis::variable<>({1.0, -1.0}), std::invalid_argument); } @@ -54,7 +55,7 @@ int main() { BOOST_TEST_EQ(a.index(std::numeric_limits::infinity()), 2); BOOST_TEST_EQ(a.index(std::numeric_limits::quiet_NaN()), 2); - BOOST_TEST_EQ(detail::cat(a), + BOOST_TEST_EQ(str(a), "variable(-1, 0, 1, metadata=\"bar\", options=underflow | overflow)"); axis::variable<> b; diff --git a/test/axis_variant_test.cpp b/test/axis_variant_test.cpp index 65173f6e..016b592d 100644 --- a/test/axis_variant_test.cpp +++ b/test/axis_variant_test.cpp @@ -11,21 +11,22 @@ #include #include #include -#include #include -#include #include #include #include #include "throw_exception.hpp" #include "utility_allocator.hpp" #include "utility_axis.hpp" - -using namespace boost::histogram; -namespace tr = axis::transform; +#include "utility_str.hpp" int main() { - { (void)axis::variant<>{}; } + using namespace boost::histogram; + namespace tr = axis::transform; + + { + (void)axis::variant<>{}; + } { using meta_type = std::vector; @@ -124,15 +125,15 @@ int main() { auto test = [](auto&& a, const char* ref) { using T = std::decay_t; axis::variant axis(std::move(a)); - BOOST_TEST_CSTR_EQ(detail::cat(axis).c_str(), ref); + BOOST_TEST_CSTR_EQ(str(axis).c_str(), ref); }; test(axis::regular<>(2, -1, 1, "regular1"), "regular(2, -1, 1, metadata=\"regular1\", options=underflow | overflow)"); struct user_defined {}; - const auto ref = detail::cat( - "integer(-1, 1, metadata=", detail::type_name(), ", options=none)"); + const auto ref = "integer(-1, 1, metadata=" + detail::type_name() + + ", options=none)"; test(axis::integer(-1, 1), ref.c_str()); } @@ -141,7 +142,7 @@ int main() { auto test = [](auto&& a, const char* ref) { using T = std::decay_t; axis::variant axis(std::move(a)); - BOOST_TEST_CSTR_EQ(detail::cat(axis.bin(0)).c_str(), ref); + BOOST_TEST_CSTR_EQ(str(axis.bin(0)).c_str(), ref); }; test(axis::regular<>(2, 1, 2), "[1, 1.5)"); @@ -190,7 +191,7 @@ int main() { BOOST_TEST_EQ(axis.index(9), 1); BOOST_TEST_EQ(axis.size(), 2); BOOST_TEST_EQ(axis.metadata(), axis::null_type{}); - BOOST_TEST_CSTR_EQ(detail::cat(axis).c_str(), ""); + BOOST_TEST_CSTR_EQ(str(axis).c_str(), ""); BOOST_TEST_THROWS(axis.value(0), std::runtime_error); axis = axis::category({"A", "B"}, "category"); diff --git a/test/detail_misc_test.cpp b/test/detail_misc_test.cpp index 2fc38dfb..abebe783 100644 --- a/test/detail_misc_test.cpp +++ b/test/detail_misc_test.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -23,9 +22,6 @@ using namespace boost::histogram::literals; namespace dtl = boost::histogram::detail; int main() { - // cat - { BOOST_TEST_EQ(dtl::cat("foo", 1, "bar"), "foo1bar"); } - // literals { BOOST_TEST_TRAIT_SAME(std::integral_constant, decltype(0_c)); diff --git a/test/utility_str.hpp b/test/utility_str.hpp new file mode 100644 index 00000000..a7f67275 --- /dev/null +++ b/test/utility_str.hpp @@ -0,0 +1,20 @@ +// Copyright 2019 Hans Dembinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_HISTOGRAM_TEST_UTILITY_STR_HPP +#define BOOST_HISTOGRAM_TEST_UTILITY_STR_HPP + +#include +#include + +template +std::string str(const T& t) { + std::ostringstream os; + os << t; + return os.str(); +} + +#endif