forked from AmbaPant/mantid
-
Notifications
You must be signed in to change notification settings - Fork 1
/
VectorOf.h
149 lines (132 loc) · 6.63 KB
/
VectorOf.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2016 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once
#include "MantidHistogramData/DllConfig.h"
#include "MantidKernel/cow_ptr.h"
#include "MantidKernel/make_cow.h"
namespace Mantid {
namespace HistogramData {
namespace detail {
/** VectorOf
This class is an implementation detail of classes like HistogramData::BinEdges
and HistogramData::Points. It wraps a copy-on-write pointer to an underlying
data type based on std::vector, such as HistogramX and HistogramY.
The first template parameter is the type of the inheriting class. This is the
CRTP (curiously recurring template pattern). This parameter is not directly
used, but guarentees that, e.g., Points and BinEdges are separate and
incompatible types, since their base class is not the same (VectorOf<Points>
and VectorOf<BinEdges>). Without this template parameter we risk that, e.g.,
assignment operators allow assigning Points to an object of type BinEdges.
The second template parameter is the type of the object to store.
@author Simon Heybrock
@date 2016
*/
template <class T, class CowType> class VectorOf {
public:
/// Default constructor, the stored object will be NULL.
VectorOf() = default;
/// Construct stored object of length count initialized to the constant value.
VectorOf(size_t count, const double &value) : m_data(Kernel::make_cow<CowType>(count, value)) {}
/// Construct stored object of length count.
explicit VectorOf(size_t count) : m_data(Kernel::make_cow<CowType>(count)) {}
/// Construct stored object with the contents of the initializer list init.
VectorOf(std::initializer_list<double> init) : m_data(Kernel::make_cow<CowType>(init)) {}
/// Copy constructor. Lightweight, stored object will be shared.
VectorOf(const VectorOf &) = default;
/// Move constructor.
VectorOf(VectorOf &&) = default;
// Note the lvalue reference qualifier for all assignment operators. This
// prevents mistakes in client code, assigning to an rvalue, such as
// histogram.getBinEdges() = { 0.1, 0.2 };
/// Copy assignment. Lightweight, stored object will be shared.
VectorOf &operator=(const VectorOf &) & = default;
/// Move assignment.
VectorOf &operator=(VectorOf &&) & = default;
/// Assigns the stored object with the contents of the initializer list init.
VectorOf &operator=(std::initializer_list<double> ilist) & {
m_data = Kernel::make_cow<CowType>(ilist);
return *this;
}
/// Constructs the stored object with the contents of the range [first, last).
template <class InputIt> VectorOf(InputIt first, InputIt last) : m_data(Kernel::make_cow<CowType>(first, last)) {}
/// Constructs the stored object of length count with contents generated by g.
template <class Generator, class = typename std::enable_if<!std::is_convertible<Generator, double>::value>::type>
VectorOf(size_t count, const Generator &g) : m_data(Kernel::make_cow<CowType>(count, g)) {}
/// Copy construct from cow_ptr. Lightweight, stored object will be shared.
explicit VectorOf(const Kernel::cow_ptr<CowType> &other) : m_data(other) {}
/// Copy construct from shared_ptr. Lightweight, stored object will be shared.
explicit VectorOf(const std::shared_ptr<CowType> &other) : m_data(other) {}
/// Copy construct stored object from data.
explicit VectorOf(const CowType &data) : m_data(Kernel::make_cow<CowType>(data)) {}
/// Move construct stored object from data.
explicit VectorOf(CowType &&data) : m_data(Kernel::make_cow<CowType>(std::move(data))) {}
/// Copy assignment from cow_ptr. Lightweight, stored object will be shared.
VectorOf &operator=(const Kernel::cow_ptr<CowType> &other) & {
m_data = other;
return *this;
}
/// Copy assignment from shared_ptr. Lightweight, stored object will be
/// shared.
VectorOf &operator=(const std::shared_ptr<CowType> &other) & {
m_data = other;
return *this;
}
/// Copy assignment to stored object from data.
VectorOf &operator=(const CowType &data) & {
if (!m_data || (&(*m_data) != &data))
m_data = Kernel::make_cow<CowType>(data);
return *this;
}
/// Move assignment to stored object from data.
VectorOf &operator=(CowType &&data) & {
if (!m_data || (&(*m_data) != &data))
m_data = Kernel::make_cow<CowType>(std::move(data));
return *this;
}
/// Assigns a constant value to stored object. The behavior is undefined if
/// the stored pointer is null.
VectorOf &operator=(const double value) & {
mutableData().assign(size(), value);
return *this;
}
/// Assigns the contents of the range [first, last)
template <class InputIt> void assign(InputIt first, InputIt last) & {
m_data = Kernel::make_cow<CowType>(first, last);
}
/// Assigns data of size count with all elements initialized to value.
void assign(size_t count, const double &value) & { m_data = Kernel::make_cow<CowType>(count, value); }
/// Checks if *this stores a non-null pointer.
explicit operator bool() const { return m_data.operator bool(); }
/// Returns true if the stored object has size 0. The behavior is undefined if
/// the stored pointer is null.
bool empty() const { return m_data->empty(); }
/// Returns the size of the stored object. The behavior is undefined if the
/// stored pointer is null.
size_t size() const { return m_data->size(); }
/// Returns a const reference to the stored object. The behavior is undefined
/// if the stored pointer is null.
const CowType &data() const { return *m_data; }
/// Returns a reference to the stored object. The behavior is undefined if the
/// stored pointer is null.
CowType &mutableData() & { return m_data.access(); }
/// Returns a copy-on-write pointer to the stored object.
Kernel::cow_ptr<CowType> cowData() const { return m_data; }
/// Returns a const reference to the internal data structure of the stored
/// object. The behavior is undefined if the stored pointer is null.
const std::vector<double> &rawData() const { return m_data->rawData(); }
/// Returns a reference to the internal data structure of the stored object.
/// The behavior is undefined if the stored pointer is null.
std::vector<double> &mutableRawData() & { return m_data.access().mutableRawData(); }
protected:
// This is used as base class only, cannot delete polymorphically, so
// destructor is protected.
~VectorOf() = default;
Kernel::cow_ptr<CowType> m_data{nullptr};
};
} // namespace detail
} // namespace HistogramData
} // namespace Mantid