reduced usage of ostringstream in exceptions

This commit is contained in:
Hans Dembinski 2019-10-28 20:08:37 +01:00 committed by GitHub
parent 3b18d9075b
commit 9669df7432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 106 additions and 127 deletions

View File

@ -10,10 +10,8 @@
#include <boost/assert.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/axes.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/make_default.hpp>
#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/indexed.hpp>
#include <boost/histogram/unsafe_access.hpp>
@ -21,6 +19,7 @@
#include <cmath>
#include <initializer_list>
#include <stdexcept>
#include <string>
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<decltype(ain)>;
BOOST_THROW_EXCEPTION(std::invalid_argument(
detail::cat(detail::type_name<A>(), " is not reducible")));
[iaxis](auto&&, const auto&) {
BOOST_THROW_EXCEPTION(std::invalid_argument("axis " + std::to_string(iaxis) +
" is not reducible"));
},
axis::get<A>(detail::axis_get(axes, iaxis)), a);
} else {

View File

@ -11,13 +11,13 @@
#include <boost/assert.hpp>
#include <boost/histogram/axis/regular.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/detail/type_name.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <iomanip>
#include <iosfwd>
#include <sstream>
#include <stdexcept>
#include <type_traits>

View File

@ -10,7 +10,6 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/histogram/axis/option.hpp>
#include <boost/histogram/detail/args_type.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/detect.hpp>
#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/detail/try_cast.hpp>
@ -22,6 +21,7 @@
#include <boost/throw_exception.hpp>
#include <boost/variant2/variant.hpp>
#include <stdexcept>
#include <string>
#include <utility>
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<A>(), " has no value method"))),
std::runtime_error(type_name<A>() + " has no value method")),
double{};
}

View File

@ -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.

View File

@ -11,7 +11,6 @@
#include <boost/histogram/axis/iterator.hpp>
#include <boost/histogram/axis/polymorphic_bin.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/relaxed_equal.hpp>
#include <boost/histogram/detail/static_if.hpp>
#include <boost/histogram/detail/type_name.hpp>
@ -20,7 +19,6 @@
#include <boost/mp11/list.hpp> // mp_first
#include <boost/throw_exception.hpp>
#include <boost/variant2/variant.hpp>
#include <ostream>
#include <stdexcept>
#include <type_traits>
#include <utility>
@ -74,9 +72,9 @@ public:
detail::static_if<is_bounded_type<U>>(
[this](const auto& u) { this->operator=(u); },
[](const auto&) {
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
detail::type_name<U>(), " is not convertible to a bounded type of ",
detail::type_name<variant>())));
BOOST_THROW_EXCEPTION(std::runtime_error(
detail::type_name<U>() + " is not convertible to a bounded type of " +
detail::type_name<variant>()));
},
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<M>(),
" through axis::variant interface which uses type ",
detail::type_name<metadata_type>(),
"; use boost::histogram::axis::get to obtain a reference "
"of this axis type")));
"cannot return metadata of type " + detail::type_name<M>() +
" through axis::variant interface which uses type " +
detail::type_name<metadata_type>() +
"; 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<M>(),
" through axis::variant interface which uses type ",
detail::type_name<metadata_type>(),
"; use boost::histogram::axis::get to obtain a reference "
"of this axis type")));
"cannot return metadata of type " + detail::type_name<M>() +
" through axis::variant interface which uses type " +
detail::type_name<metadata_type>() +
"; use boost::histogram::axis::get to obtain a reference "
"of this axis type"));
},
a);
},

View File

@ -22,6 +22,7 @@
#include <boost/mp11/utility.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
@ -57,9 +58,10 @@ template <class T>
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=<new max size> "
"to increase internal buffers"));
}
// tuple is never too large because internal buffers adapt to size of tuple

View File

@ -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 <boost/config.hpp>
#include <sstream>
namespace boost {
namespace histogram {
namespace detail {
BOOST_ATTRIBUTE_UNUSED inline void cat_impl(std::ostringstream&) {}
template <typename T, typename... Ts>
void cat_impl(std::ostringstream& os, const T& t, const Ts&... ts) {
os << t;
cat_impl(os, ts...);
}
template <typename... Ts>
std::string cat(const Ts&... args) {
std::ostringstream os;
cat_impl(os, args...);
return os.str();
}
} // namespace detail
} // namespace histogram
} // namespace boost
#endif

View File

@ -9,11 +9,11 @@
#include <boost/config.hpp>
#include <boost/core/demangle.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/type_name.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
#include <string>
#include <type_traits>
namespace boost {
@ -21,7 +21,7 @@ namespace histogram {
namespace detail {
template <class T, class E, class U>
BOOST_NORETURN T try_cast_impl(mp11::mp_int<0>, U&&) {
BOOST_THROW_EXCEPTION(E(cat("cannot cast ", type_name<T>(), " to ", type_name<U>())));
BOOST_THROW_EXCEPTION(E("cannot cast " + type_name<T>() + " to " + type_name<U>()));
}
template <class T, class E, class U>

View File

@ -9,7 +9,6 @@
#include <boost/core/typeinfo.hpp>
#include <boost/type.hpp>
#include <sstream>
#include <string>
namespace boost {
@ -17,31 +16,28 @@ namespace histogram {
namespace detail {
template <class T>
std::ostream& type_name_impl(std::ostream& os, boost::type<T>) {
os << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
return os;
std::string type_name_impl(boost::type<T>) {
return boost::core::demangled_name(BOOST_CORE_TYPEID(T));
}
template <class T>
std::ostream& type_name_impl(std::ostream& os, boost::type<const T>) {
return type_name_impl(os, boost::type<T>{}) << " const";
std::string type_name_impl(boost::type<const T>) {
return type_name_impl(boost::type<T>{}) + " const";
}
template <class T>
std::ostream& type_name_impl(std::ostream& os, boost::type<T&>) {
return type_name_impl(os, boost::type<T>{}) << "&";
std::string type_name_impl(boost::type<T&>) {
return type_name_impl(boost::type<T>{}) + " &";
}
template <class T>
std::ostream& type_name_impl(std::ostream& os, boost::type<T&&>) {
return type_name_impl(os, boost::type<T>{}) << "&&";
std::string type_name_impl(boost::type<T&&>) {
return type_name_impl(boost::type<T>{}) + " &&";
}
template <class T>
std::string type_name() {
std::ostringstream os;
type_name_impl(os, boost::type<T>{});
return os.str();
return type_name_impl(boost::type<T>{});
}
} // namespace detail

View File

@ -10,7 +10,6 @@
#include <algorithm>
#include <boost/core/nvp.hpp>
#include <boost/histogram/detail/array_wrapper.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/detect.hpp>
#include <boost/histogram/detail/iterator_adaptor.hpp>
#include <boost/histogram/detail/safe_comparison.hpp>
@ -90,20 +89,19 @@ struct array_impl : T {
template <class U, class = requires_iterable<U>>
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;
}

View File

@ -9,7 +9,6 @@
#include <boost/histogram/axis/category.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <limits>
#include <sstream>
#include <string>
@ -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<axis::category<int>>::value);
BOOST_TEST(std::is_nothrow_move_constructible<axis::category<std::string>>::value);
BOOST_TEST(std::is_nothrow_move_assignable<axis::category<int>>::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

View File

@ -7,16 +7,17 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/axis/integer.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <limits>
#include <sstream>
#include <type_traits>
#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<axis::integer<>>::value);
BOOST_TEST(std::is_nothrow_move_constructible<axis::integer<>>::value);
@ -44,7 +45,7 @@ int main() {
BOOST_TEST_EQ(a.index(10), 3);
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::quiet_NaN()), 3);
BOOST_TEST_EQ(detail::cat(a),
BOOST_TEST_EQ(str(a),
"integer(-1, 2, metadata=\"bar\", options=underflow | overflow)");
axis::integer<double> 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

View File

@ -7,7 +7,6 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/axis/regular.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <limits>
#include <sstream>
#include <type_traits>
@ -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<axis::regular<>>::value);
BOOST_TEST(std::is_nothrow_move_constructible<axis::regular<>>::value);
@ -73,7 +73,7 @@ int main() {
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::infinity()), 4);
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::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<double, tr::log>{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<double>::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<double>::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<float, def, axis::null_type>(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

View File

@ -7,14 +7,15 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/axis/variable.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <limits>
#include <sstream>
#include <type_traits>
#include <vector>
#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<double>(0);
BOOST_TEST_THROWS((axis::variable<>(empty)), std::invalid_argument);
BOOST_TEST_THROWS(axis::variable<>(std::vector<double>{}), 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<double>::infinity()), 2);
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::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;

View File

@ -11,21 +11,22 @@
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/axis/regular.hpp>
#include <boost/histogram/axis/variant.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/type_name.hpp>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
#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<int>;
@ -124,15 +125,15 @@ int main() {
auto test = [](auto&& a, const char* ref) {
using T = std::decay_t<decltype(a)>;
axis::variant<T> 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<user_defined>(), ", options=none)");
const auto ref = "integer(-1, 1, metadata=" + detail::type_name<user_defined>() +
", options=none)";
test(axis::integer<int, user_defined, axis::option::none_t>(-1, 1), ref.c_str());
}
@ -141,7 +142,7 @@ int main() {
auto test = [](auto&& a, const char* ref) {
using T = std::decay_t<decltype(a)>;
axis::variant<T> 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(), "<unstreamable>");
BOOST_TEST_CSTR_EQ(str(axis).c_str(), "<unstreamable>");
BOOST_TEST_THROWS(axis.value(0), std::runtime_error);
axis = axis::category<std::string>({"A", "B"}, "category");

View File

@ -7,7 +7,6 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/histogram/accumulators/weighted_sum.hpp>
#include <boost/histogram/detail/cat.hpp>
#include <boost/histogram/detail/common_type.hpp>
#include <boost/histogram/detail/counting_streambuf.hpp>
#include <boost/histogram/detail/non_member_container_access.hpp>
@ -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<unsigned, 0>, decltype(0_c));

20
test/utility_str.hpp Normal file
View File

@ -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 <sstream>
#include <string>
template <class T>
std::string str(const T& t) {
std::ostringstream os;
os << t;
return os.str();
}
#endif