| 263 | */ |
| 264 | template <typename RealType, typename Allocator> |
| 265 | class variable : public labeled_base<Allocator>, |
| 266 | public iterator_mixin<variable<RealType, Allocator>> { |
| 267 | using base_type = labeled_base<Allocator>; |
| 268 | |
| 269 | public: |
| 270 | using allocator_type = typename base_type::allocator_type; |
| 271 | using value_type = RealType; |
| 272 | using bin_type = interval_view<variable>; |
| 273 | |
| 274 | private: |
| 275 | using value_allocator_type = |
| 276 | typename std::allocator_traits<allocator_type>::template rebind_alloc<value_type>; |
| 277 | |
| 278 | public: |
| 279 | /** Construct an axis from bin edges. |
| 280 | * |
| 281 | * \param x sequence of bin edges. |
| 282 | * \param label description of the axis. |
| 283 | * \param uoflow whether to add under-/overflow bins. |
| 284 | */ |
| 285 | variable(std::initializer_list<value_type> x, string_view label = {}, |
| 286 | uoflow_type uo = uoflow_type::on, const allocator_type& a = allocator_type()) |
| 287 | : variable(x.begin(), x.end(), label, uo, a) {} |
| 288 | |
| 289 | template <typename Iterator, |
| 290 | typename = boost::histogram::detail::requires_iterator<Iterator>> |
| 291 | variable(Iterator begin, Iterator end, string_view label = {}, |
| 292 | uoflow_type uo = uoflow_type::on, const allocator_type& a = allocator_type()) |
| 293 | : base_type(begin == end ? 0 : std::distance(begin, end) - 1, uo, label, a) { |
| 294 | value_allocator_type a2(a); |
| 295 | using AT = std::allocator_traits<value_allocator_type>; |
| 296 | x_ = AT::allocate(a2, nx()); |
| 297 | auto xit = x_; |
| 298 | AT::construct(a2, xit, *begin++); |
| 299 | while (begin != end) { |
| 300 | if (*begin <= *xit) |
| 301 | throw std::invalid_argument("input sequence must be strictly ascending"); |
| 302 | AT::construct(a2, ++xit, *begin++); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | variable() = default; |
| 307 | |
| 308 | variable(const variable& o) : base_type(o) { |
| 309 | value_allocator_type a(o.get_allocator()); |
| 310 | using AT = std::allocator_traits<value_allocator_type>; |
| 311 | x_ = AT::allocate(a, nx()); |
| 312 | auto it = o.x_; |
| 313 | for (auto xit = x_, xe = xend(); xit != xe; ++xit) AT::construct(a, xit, *it++); |
| 314 | } |
| 315 | |
| 316 | variable& operator=(const variable& o) { |
| 317 | if (this != &o) { |
| 318 | if (base_type::size() != o.size()) { |
| 319 | this->~variable(); |
| 320 | base::operator=(o); |
| 321 | value_allocator_type a(base_type::get_allocator()); |
| 322 | using AT = std::allocator_traits<value_allocator_type>; |