Multi Type Vector
Quick start
The following code demonstrates a simple use case of storing values of double
and std::string
types in a single container using multi_type_vector
.
#include <mdds/multi_type_vector.hpp>
#include <mdds/multi_type_vector/trait.hpp>
#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::endl;
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func>;
template<typename _Blk>
void print_block(const mtv_type::value_type& v)
{
// Each element block has static begin() and end() methods that return
// begin and end iterators, respectively, from the passed element block
// instance.
auto it = _Blk::begin(*v.data);
auto it_end = _Blk::end(*v.data);
std::for_each(it, it_end,
[](const typename _Blk::value_type& elem)
{
cout << " * " << elem << endl;
}
);
}
int main() try
{
mtv_type con(20); // Initialized with 20 empty elements.
// Set values individually.
con.set(0, 1.1);
con.set(1, 1.2);
con.set(2, 1.3);
// Set a sequence of values in one step.
std::vector<double> vals = { 10.1, 10.2, 10.3, 10.4, 10.5 };
con.set(3, vals.begin(), vals.end());
// Set string values.
con.set(10, std::string("Andy"));
con.set(11, std::string("Bruce"));
con.set(12, std::string("Charlie"));
// Iterate through all blocks and print all elements.
for (const mtv_type::value_type& v : con)
{
switch (v.type)
{
case mdds::mtv::element_type_double:
{
cout << "numeric block of size " << v.size << endl;
print_block<mdds::mtv::double_element_block>(v);
break;
}
case mdds::mtv::element_type_string:
{
cout << "string block of size " << v.size << endl;
print_block<mdds::mtv::string_element_block>(v);
break;
}
case mdds::mtv::element_type_empty:
cout << "empty block of size " << v.size << endl;
cout << " - no data - " << endl;
default:
;
}
}
return EXIT_SUCCESS;
}
catch (...)
{
return EXIT_FAILURE;
}
You’ll see the following console output when you compile and execute this code:
numeric block of size 8
* 1.1
* 1.2
* 1.3
* 10.1
* 10.2
* 10.3
* 10.4
* 10.5
empty block of size 2
- no data -
string block of size 3
* Andy
* Bruce
* Charlie
empty block of size 7
- no data -

Logical structure between the primary array, blocks, and element blocks.
Each multi_type_vector instance maintains a logical storage structure of one
primary array containing one or more blocks each of which consists of type
,
position
, size
and data
members:
type
- numeric value representing the block type.position
- numeridc value representing the logical position of the first element of the block.size
- number of elements present in the block a.k.a its logical size.data
- pointer to the secondary storage (element block) storing the element values.
In this example code, the type
member is referenced to determine its block
type and its logical size is determined from the size
member. For the
numeric and string blocks, their data
members, which should point to the
memory addresses of their respective element blocks, are dereferenced in order
to print out their element values to stdout inside the print_block
function.
Use custom event handlers
It is also possible to define custom event handlers that get called when certain events take place. To define custom event handlers, you need to define either a class or a struct that has the following methods:
void element_block_acquired(mdds::mtv::base_element_block* block)
void element_block_released(mdds::mtv::base_element_block* block)
as its public methods, specify it as type named event_func
in a trait struct,
and pass it as the second template argument when instantiating your
multi_type_vector
type. Refer to mdds::mtv::empty_event_func
for the detail on when each event handler method gets triggered.
The following code example demonstrates how this all works:
#include <mdds/multi_type_vector.hpp>
#include <mdds/multi_type_vector/trait.hpp>
#include <iostream>
using std::cout;
using std::endl;
class event_hdl
{
public:
void element_block_acquired(mdds::mtv::base_element_block* block)
{
(void)block;
cout << " * element block acquired" << endl;
}
void element_block_released(mdds::mtv::base_element_block* block)
{
(void)block;
cout << " * element block released" << endl;
}
};
struct trait
{
using event_func = event_hdl;
constexpr static mdds::mtv::lu_factor_t loop_unrolling = mdds::mtv::lu_factor_t::none;
};
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func, trait>;
int main() try
{
mtv_type db; // starts with an empty container.
cout << "inserting string 'foo'..." << endl;
db.push_back(std::string("foo")); // creates a new string element block.
cout << "inserting string 'bah'..." << endl;
db.push_back(std::string("bah")); // appends to an existing string block.
cout << "inserting int 100..." << endl;
db.push_back(int(100)); // creates a new int element block.
cout << "emptying the container..." << endl;
db.clear(); // releases both the string and int element blocks.
cout << "exiting program..." << endl;
return EXIT_SUCCESS;
}
catch (...)
{
return EXIT_FAILURE;
}
You’ll see the following console output when you compile and execute this code:
inserting string 'foo'...
* element block acquired
inserting string 'bah'...
inserting int 100...
* element block acquired
emptying the container...
* element block released
* element block released
exiting program...
In this example, the element_block_acquired handler gets triggered each time the container creates (thus acquires) a new element block to store a value. It does not get called when a new value is appended to a pre-existing element block. Similarly, the element_block_releasd handler gets triggered each time an existing element block storing non-empty values gets deleted. One thing to keep in mind is that since these two handlers respond to events related to element blocks which are owned by non-empty blocks in the primary array, and empty blocks don’t store any element block instances, creations or deletions of empty blocks don’t trigger these event handlers.
The trait also allows you to configure other behaviors of multi_type_vector
.
Refer to mdds::mtv::default_trait
for all available parameters.
Get raw pointer to element block array
Sometimes you need to expose a pointer to an element block array
especially when you need to pass such an array pointer to C API that
requires one. You can do this by calling the data
method of the
element_block template class . This works since the element block
internally just wraps std::vector
(or
std::deque
in case the MDDS_MULTI_TYPE_VECTOR_USE_DEQUE
preprocessing macro is defined), and its data
method simply exposes
vector’s own data
method which returns the memory location of its
internal array storage.
The following code demonstrates this by exposing raw array pointers to the internal arrays of numeric and string element blocks, and printing their element values directly from these array pointers.
#include <mdds/multi_type_vector.hpp>
#include <mdds/multi_type_vector/trait.hpp>
#include <iostream>
using std::cout;
using std::endl;
using mdds::mtv::double_element_block;
using mdds::mtv::string_element_block;
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func>;
int main() try
{
mtv_type db; // starts with an empty container.
db.push_back(1.1);
db.push_back(1.2);
db.push_back(1.3);
db.push_back(1.4);
db.push_back(1.5);
db.push_back(std::string("A"));
db.push_back(std::string("B"));
db.push_back(std::string("C"));
db.push_back(std::string("D"));
db.push_back(std::string("E"));
// At this point, you have 2 blocks in the container.
cout << "block size: " << db.block_size() << endl;
cout << "--" << endl;
// Get an iterator that points to the first block in the primary array.
mtv_type::const_iterator it = db.begin();
// Get a pointer to the raw array of the numeric element block using the
// 'data' method.
const double* p = double_element_block::data(*it->data);
// Print the elements from this raw array pointer.
for (const double* p_end = p + it->size; p != p_end; ++p)
cout << *p << endl;
cout << "--" << endl;
++it; // move to the next block, which is a string block.
// Get a pointer to the raw array of the string element block.
const std::string* pz = string_element_block::data(*it->data);
// Print out the string elements.
for (const std::string* pz_end = pz + it->size; pz != pz_end; ++pz)
cout << *pz << endl;
return EXIT_SUCCESS;
}
catch (...)
{
return EXIT_FAILURE;
}
Compiling and execute this code produces the following output:
block size: 2
--
1.1
1.2
1.3
1.4
1.5
--
A
B
C
D
E
Traverse multiple multi_type_vector instances “sideways”
In this section we will demonstrate a way to traverse multiple instances of
multi_type_vector
“sideways” using the
mdds::mtv::collection
class. What this class does is to wrap
multiple instances of multi_type_vector
and generate
iterators that let you iterate the individual element values collectively in
the direction orthogonal to the direction of the individual vector instances.
The best way to explain this feature is to use a spreadsheet analogy. Let’s say we are implementing a data store to store a 2-dimensional tabular data where each cell in the data set is associated with row and column indices. Each cell may store a value of string type, integer type, numeric type, etc. And let’s say that the data looks like the following spreadsheet data:

It consists of five columns, with each column storing 21 rows of data. The
first row is a header row, followed by 20 rows of values. In this example, We
will be using one multi_type_vector
instance for each
column thus creating five instances in total, and store them in a
std::vector
container.
The declaration of the data store will look like this:
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func>;
using collection_type = mdds::mtv::collection<mtv_type>;
std::vector<mtv_type> columns(5);
The first two lines specify the concrete multi_type_vector
type used for each individual column and the collection type that wraps the
columns. The third line instantiates the std::vector
instance to store
the columns, and we are setting its size to five to accommodate for five
columns. We will make use of the collection_type later in this example after
the columns have been populated.
Now, we need to populate the columns with values. First, we are setting the header row:
// Populate the header row.
const char* headers[] = { "ID", "Make", "Model", "Year", "Color" };
size_t i = 0;
for (const char* v : headers)
columns[i++].push_back<std::string>(v);
We are then filling each column individually from column 1 through column 5. First up is column 1:
// Fill column 1.
int c1_values[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
for (int v : c1_values)
columns[0].push_back(v);
Hopefully this code is straight-forward. It initializes an array of values
and push them to the column one at a time via
push_back()
. Next up is column 2:
// Fill column 2.
const char* c2_values[] =
{
"Nissan", "Mercedes-Benz", "Nissan", "Suzuki", "Saab", "Subaru", "GMC", "Mercedes-Benz", "Toyota", "Nissan",
"Mazda", "Dodge", "Ford", "Bentley", "GMC", "Audi", "GMC", "Mercury", "Pontiac", "BMW",
};
for (const char* v : c2_values)
columns[1].push_back<std::string>(v);
This is similar to the code for column 1, except that because we are using an
array of string literals which implicitly becomes an initializer list of type
const char*
, we need to explicitly specify the type for the
push_back()
call to be std::string
.
The code for column 3 is very similar to this:
// Fill column 3.
const char* c3_values[] =
{
"Frontier", "W201", "Frontier", "Equator", "9-5", "Tribeca", "Yukon XL 2500", "E-Class", "Camry Hybrid", "Frontier",
"MX-5", "Ram Van 1500", "Edge", "Azure", "Sonoma Club Coupe", "S4", "3500 Club Coupe", "Villager", "Sunbird", "3 Series",
};
for (const char* v : c3_values)
columns[2].push_back<std::string>(v);
Populating column 4 needs slight pre-processing. We are inserting a string value of “unknown” in lieu of an integer value of -1. Therefore the following code will do:
// Fill column 4. Replace -1 with "unknown".
int32_t c4_values[] =
{
1998, 1986, 2009, -1, -1, 2008, 2009, 2008, 2010, 2001,
2008, 2000, -1, 2009, 1998, 2013, 1994, 2000, 1990, 1993,
};
for (int32_t v : c4_values)
{
if (v < 0)
// Insert a string value "unknown".
columns[3].push_back<std::string>("unknown");
else
columns[3].push_back(v);
}
Finally, the last column to fill, which uses the same logic as for columns 2 and 3:
// Fill column 5
const char* c5_values[] =
{
"Turquoise", "Fuscia", "Teal", "Fuscia", "Green", "Khaki", "Pink", "Goldenrod", "Turquoise", "Yellow",
"Orange", "Goldenrod", "Fuscia", "Goldenrod", "Mauv", "Crimson", "Turquoise", "Teal", "Indigo", "LKhaki",
};
for (const char* v : c5_values)
columns[4].push_back<std::string>(v);
At this point, the content we’ve put into the columns
variable roughly
reflects the tabular data shown at the beginning of this section. Now we can
use the collection type we’ve declared earlier to wrap the columns:
// Wrap the columns with the 'collection'...
collection_type rows(columns.begin(), columns.end());
We are naming this variable rows
since what we are doing with this wrapper
is to traverse the content of the tabular data in row-wise direction. For
this reason, calling it rows
is quite fitting.
The collection
class offers some flexibility as to
how the instances that you are trying to traverse orthogonally are stored.
That being said, you must meet the following prerequisites when passing the
collection of vector instances to the constructor of the
collection
class:
All
multi_type_vector
instances that comprise the collection must be of the same logical length i.e. theirsize()
methods must all return the same value.The instances in the collection must be stored in the source container either as
concrete instances (as in this example),
as pointers, or
as heap instances wrapped within smart pointer class such as
std::shared_ptr
orstd::unique_ptr
.
Although we are storing the vector instances in a std::vector
container in
this example, you have the flexibility to pick a different type of container
to store the individual vector instances as long as it provides STL-compatible
standard iterator functionality.
Additionally, when using the collection
class, you
must ensure that the content of the vector instances that it references will
not change for the duration of its use.
Finally, here is the code that does the traversing:
// Traverse the tabular data in row-wise direction.
for (const auto& cell : rows)
{
if (cell.index > 0)
// Insert a column separator before each cell except for the ones in the first column.
std::cout << " | ";
switch (cell.type)
{
// In this example, we use two element types only.
case mdds::mtv::element_type_int32:
std::cout << cell.get<mdds::mtv::int32_element_block>();
break;
case mdds::mtv::element_type_string:
std::cout << cell.get<mdds::mtv::string_element_block>();
break;
default:
std::cout << "???"; // The default case should not hit in this example.
}
if (cell.index == 4)
// We are in the last column. Insert a line break.
std::cout << std::endl;
}
It’s a simple for-loop, and in each iteration you get a single cell node that contains metadata about that cell including its value. The node contains the following members:
type
- an integer value representing the type of the value.index
- a 0-based index of themulti_type_vector
instance within the collection. You can think of this as column index in this example.position
- a 0-based logical element position within eachmulti_type_vector
instance. You can think of this as row index in this example.
In the current example we are only making use of the type
and index
members, but the position
member will be there if you need it.
The node also provides a convenient get()
method to fetch the value of the
cell. This method is a template method, and you need to explicitly specify
the element block type in order to access the value.
When executing this code, you will see the following outout:
ID | Make | Model | Year | Color
1 | Nissan | Frontier | 1998 | Turquoise
2 | Mercedes-Benz | W201 | 1986 | Fuscia
3 | Nissan | Frontier | 2009 | Teal
4 | Suzuki | Equator | unknown | Fuscia
5 | Saab | 9-5 | unknown | Green
6 | Subaru | Tribeca | 2008 | Khaki
7 | GMC | Yukon XL 2500 | 2009 | Pink
8 | Mercedes-Benz | E-Class | 2008 | Goldenrod
9 | Toyota | Camry Hybrid | 2010 | Turquoise
10 | Nissan | Frontier | 2001 | Yellow
11 | Mazda | MX-5 | 2008 | Orange
12 | Dodge | Ram Van 1500 | 2000 | Goldenrod
13 | Ford | Edge | unknown | Fuscia
14 | Bentley | Azure | 2009 | Goldenrod
15 | GMC | Sonoma Club Coupe | 1998 | Mauv
16 | Audi | S4 | 2013 | Crimson
17 | GMC | 3500 Club Coupe | 1994 | Turquoise
18 | Mercury | Villager | 2000 | Teal
19 | Pontiac | Sunbird | 1990 | Indigo
20 | BMW | 3 Series | 1993 | LKhaki
which clearly shows that the code has traversed the content of the tabular data horizontally across columns as intended.
Now, one feature that may come in handy is the ability to limit the iteration
range within the collection. You can do that by calling either
set_collection_range()
to limit the column
range or set_element_range()
to limit the
row range, or perhaps both.
Let’s see how this works in the current example. Here, we are going to limit the iteration range to only columns 2 and 3, and rows 2 through 11. The following code will set this limit:
rows.set_collection_range(1, 2); // only columns 2 and 3.
rows.set_element_range(1, 10); // only rows 2 through 11.
Then iterate through the collection once again:
for (const auto& cell : rows)
{
if (cell.index > 1)
// Insert a column separator before each cell except for the ones in the first column.
std::cout << " | ";
switch (cell.type)
{
// In this example, we use two element types only.
case mdds::mtv::element_type_int32:
std::cout << cell.get<mdds::mtv::int32_element_block>();
break;
case mdds::mtv::element_type_string:
std::cout << cell.get<mdds::mtv::string_element_block>();
break;
default:
std::cout << "???"; // The default case should not hit in this example.
}
if (cell.index == 2)
// We are in the last column. Insert a line break.
std::cout << std::endl;
}
This code is nearly identical to the previous one except for the index values used to control when to insert column separators and line breaks at the top and bottom of each iteration. When executing this code, you’ll see the following output:
Nissan | Frontier
Mercedes-Benz | W201
Nissan | Frontier
Suzuki | Equator
Saab | 9-5
Subaru | Tribeca
GMC | Yukon XL 2500
Mercedes-Benz | E-Class
Toyota | Camry Hybrid
Nissan | Frontier
which clearly shows that your iteration range did indeed shrink as expected.
Performance Considerations
Select SoA or AoS storage types
If you instantiate a multi_type_vector instance via
mdds::multi_type_vector
, which is an alias type for
mdds::mtv::soa::multi_type_vector
, you will be using the
structure-of-arrays (SoA) variant of its implementation which is new in 2.0.
Prior to 2.0, multi_type_vector used the array-of-structures (AoS) layout which
is still available post 2.0 via mdds::mtv::aos::multi_type_vector
in case you need it.
Note, however, that the SoA variant generally yields better overall performance since it can make more efficient use of CPU caches. It is therefore highly recommended that you stick with the SoA variant unless you have a specific reason not to.
Also note that both variants are API compatibile with each other.
Use of position hints to avoid the cost of block position lookup
Consider the following example code:
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func>;
size_t size = 50000;
// Initialize the container with one empty block of size 50000.
mtv_type db(size);
// Set non-empty value at every other logical position from top down.
for (size_t i = 0; i < size; ++i)
{
if (i % 2)
db.set<double>(i, 1.0);
}
which, when executed, may take quite sometime to complete especially when you are using an older version of mdds. This particular example exposes one weakness that multi_type_vector has; because it needs to first look up the position of the block to operate with, and that lookup always starts from the first block, the time it takes to find the correct block increases as the number of blocks goes up. This example demonstrates the worst case scenario of such lookup complexity since it always inserts the next value at the last block position.
Fortunately, there is a simple solution to this which the following code demonstrates:
using mtv_type = mdds::multi_type_vector<mdds::mtv::element_block_func>;
size_t size = 50000;
// Initialize the container with one empty block of size 50000.
mtv_type db(size);
mtv_type::iterator pos = db.begin();
// Set non-empty value at every other logical position from top down.
for (size_t i = 0; i < size; ++i)
{
if (i % 2)
// Pass the position hint as the first argument, and receive a new
// one returned from the method for the next call.
pos = db.set<double>(pos, i, 1.0);
}
Compiling and executing this code should take only a fraction of a second.
The only difference between the second example and the first one is that the
second one uses an interator as a position hint to keep track of the position of
the last modified block. Each
set()
method call returns an
iterator which can then be passed to the next
set()
call as the position hint.
Because an iterator object internally stores the location of the block the value
was inserted to, this lets the method to start the block position lookup process
from the last modified block, which in this example is always one block behind
the one the new value needs to go. Using the big-O notation, the use of the
position hint essentially turns the complexity of O(n^2) in the first example
into O(1) in the second one if you are using an older version of mdds where the
block position lookup had a linear complexity.
This strategy should work with any methods in multi_type_vector
that take a position hint as the first argument.
Note that, if you are using a more recent version of mdds (1.6.0 or newer), the cost of block position lookup is significantly lessoned thanks to the switch to binary search in performing the lookup.
Note
If you are using mdds 1.6.0 or newer, the cost of block position lookup is much less significant even without the use of position hints. But the benefit of using position hints may still be there. It’s always a good idea to profile your specific use case and decide whether the use of position hints is worth it.
One important thing to note is that, as a user, you must ensure that the position hint you pass stays valid between the calls. A position hint becomes invalid when the content of the container changes. A good strategy to maintain a valid position hint is to always receive the iterator returned from the mutator method you called to which you passed the previous position hint, which is what the code above does. Passing an invalid position hint to a method that takes one may result in invalid memory access or otherwise in some sort of undefined behavior.
Warning
You must ensure that the position hint you pass stays valid. Passing an invalid position hint to a method that takes one may result in invalid memory access or otherwise in some sort of undefined behavior.
Block shifting performance and loop-unrolling factor
The introduction of binary search in the block position lookup implementation in version 1.6 has significantly improved its lookup performance, but has also resulted in slight performance hit when shifting blocks during value insertion. This is because when shifting the logical positions of the blocks below the insertion point, their head positions need to be re-calculated to account for their new positions.
The good news is that the switch to the structure-of-arrays (SoA) storage layout in 2.0 alone may bring subtle but measurable improvement in the block position adjustment performance due to the logical block positions now being stored in a separate array thereby improving its cache efficiency. In reality, however, this was somewhat dependent on the CPU types since some CPU’s didn’t show any noticeable improvements or even showed worse performance, while other CPU types showed consistent improvements with SoA over AoS.
Another factor that may play a role is loop unrolling
factor which can be configured via the loop_unrolling
variable in your custom trait type if you use version 2.0 or newer. This variable
is an enum class of type mdds::mtv::lu_factor_t
which enumerates
several pre-defined loop-unrolling factors as well as some SIMD features.
The hardest part is to figure out which loop unrolling factor is the best option in your runtime environment, since it is highly dependent on the environment. Luckily mdds comes with a tool called runtime-env which, when run, will perform some benchmarks and give you the best loop-unrolling factor in your runtime environment. Be sure to build this tool with the same compiler and compiler flags as your target program in order for this tool to give you a representative answer.
Debugging
Tracing of public methods
When using multi_type_vector
to handle a series
of data reads and writes in an non-trivial code base, sometimes you may find
yourself needing to track which methods are getting called when following a
certain code path during a debugging session. In such a situation, you can enable
an optional trace method which gets called whenever a public method of multi_type_vector
is called.
First, you need to define a preprocessor macro named
MDDS_MULTI_TYPE_VECTOR_DEBUG
before including the header for
multi_type_vector
:
#define MDDS_MULTI_TYPE_VECTOR_DEBUG 1
#include <mdds/multi_type_vector/soa/main.hpp>
#include <mdds/multi_type_vector/trait.hpp>
#include <iostream>
to enable additional debug code. In this example the value of the macro is set to 1, but it doesn’t matter what the value of the macro is, as long as it is defined. You can also define one as a compiler option as well.
Once defined, the next step is to add a trace
method as a static function to
the trait type you pass as a template argument of multi_type_vector:
namespace mtv = mdds::mtv;
struct mtv_trait : public mtv::default_trait
{
static void trace(const mtv::trace_method_properties_t& props)
{
std::cout << "function:" << std::endl
<< " name: " << props.function_name << std::endl
<< " args: " << props.function_args << std::endl;
}
};
using mtv_type = mtv::soa::multi_type_vector<mtv::element_block_func, mtv_trait>;
Here, we are simply inheriting our trait type from the
default_trait
type and simply adding a static trace
function to it, and passing this trait type to the mtv_type definition below.
This trace function must take one argument of type
mdds::mtv::trace_method_properties_t
which includes various
properties of the traced call. In this example, we are simply printing the
properties named
function_name
and
function_args
each time a
traced method is called. Both of these properties are printable string types.
Note that this trace
function is entirely optional; the code will compile
fine even when it’s not defined. Also, it must be declared as static for it to
be called.
Let’s instantiate an object of mtv_type
, call some of its methods and see
what happens. When executing the following code:
mtv_type db(10);
db.set<int32_t>(0, 12);
db.set<int8_t>(2, 34);
db.set<int16_t>(4, 56);
You will see the following output:
function:
name: multi_type_vector
args: init_size=10
function:
name: set
args: pos=0; value=? (type=5)
function:
name: set
args: pos=2; value=? (type=1)
function:
name: set
args: pos=4; value=? (type=3)
function:
name: ~multi_type_vector
args:
The function_name
property is hopefully self-explanatory. The
function_args
property is
a single string value containing the information about the function’s
arguments and optionally their values if their values are known to be
printable. If the value of an argument cannot be printed, ?
is placed
instead. For some argument types, an additional information is displayed e.g.
(type=5)
in the above output which indicates that the type of the value
being passed to the function is element_type_int32
.
If you want to limit your tracing to a specific function type or types, you
can make use of the type
property which specifies the type of the traced method. Likewise, if you want
to only trace methods of a certain instance, use
instance
to filter the
incoming trace calls based on the memory addresses of the instances whose
methods are being traced.
Note that this feature is available for version 2.0.2 and newer, and currently
only available for the SoA variant of multi_type_vector
.
Note
This feature is only available for version 2.0.2 and newer, and only for the SoA variant.
API Reference
Core
mdds::multi_type_vector
-
template<typename ElemBlockFunc, typename Trait = mtv::default_trait>
using mdds::multi_type_vector = mtv::soa::multi_type_vector<ElemBlockFunc, Trait> Type alias for the concrete implementation to maintain backward API compatibility.
mdds::mtv::soa::multi_type_vector
-
template<typename ElemBlockFunc, typename Trait = mdds::mtv::default_trait>
class mdds::mtv::soa::multi_type_vector Multi-type vector consists of a series of one or more blocks, and each block may either be empty, or stores a series of non-empty elements of identical type. These blocks collectively represent a single logical one-dimensional array that may store elements of different types. It is guaranteed that the block types of neighboring blocks are always different.
Structurally, the primary array stores block instances whose types are of
value_type
, which in turn consists of the following data members:type
which indicates the block type,position
which stores the logical position of the first element of the block,size
which stores the logical size of the block, anddata
which stores the pointer to a secondary array (a.k.a. element block) which stores the actual element values, ornullptr
in case the block represents an empty segment.
This variant implements a structure-of-arrays (SoA) storage.
Public Types
-
using size_type = std::size_t
-
using element_block_type = mdds::mtv::base_element_block
-
using element_block_func = ElemBlockFunc
-
using event_func = typename Trait::event_func
Optional event handler function structure, whose functions get called at specific events. The following events are currently supported:
element_block_acquired
- this gets called whenever the container acquires a new element block either as a result of a new element block creation or a tranfer of an existing element block from another container.element_block_released
- this gets called whenever the container releases an existing element block either because the block gets deleted or gets transferred to another container.
See also
mdds::mtv::empty_event_func for the precise function signatures of the event handler functions.
-
using iterator = detail::iterator_base<iterator_trait>
-
using reverse_iterator = detail::iterator_base<reverse_iterator_trait>
-
using const_reverse_iterator = detail::const_iterator_base<const_reverse_iterator_trait, reverse_iterator>
-
using const_position_type = std::pair<const_iterator, size_type>
-
using value_type = mdds::detail::mtv::iterator_value_node<multi_type_vector, size_type>
value_type is the type of a block stored in the primary array. It consists of the following data members:
type
which indicates the block type,position
which stores the logical position of the first element of the block,size
which stores the logical size of the block, anddata
which stores the pointer to a secondary array (a.k.a. element block) which stores the actual element values, ornullptr
in case the block represents an empty segment.
Public Functions
-
event_func &event_handler()
-
const event_func &event_handler() const
-
multi_type_vector()
Default constructor. It initializes the container with empty size.
-
multi_type_vector(const event_func &hdl)
Constructor that takes an lvalue reference to an event handler object. The event handler instance will be copy-constructed.
- Parameters
hdl – lvalue reference to an event handler object.
-
multi_type_vector(event_func &&hdl)
Constructor that takes an rvalue reference to an event handler object. The event handler instance will be move-constructed.
- Parameters
hdl – rvalue reference to an event handler object.
-
multi_type_vector(size_type init_size)
Constructor that takes initial size of the container. When the size specified is greater than 0, it initializes the container with empty elements.
- Parameters
init_size – initial container size.
-
template<typename T>
multi_type_vector(size_type init_size, const T &value) Constructor that takes initial size of the container and an element value to initialize the elements to. When the size specified is greater than 0, it initializes the container with elements that are copies of the value specified.
- Parameters
init_size – initial container size.
value – initial element value.
-
template<typename T>
multi_type_vector(size_type init_size, const T &it_begin, const T &it_end) Constructor that takes initial size of the container and begin and end iterator positions that specify a series of elements to initialize the container to. The container will contain copies of the elements specified after this call returns.
- Parameters
init_size – initial container size.
it_begin – iterator that points to the begin position of the values the container is being initialized to.
it_end – iterator that points to the end position of the values the container is being initialized to. The end position is not inclusive.
-
multi_type_vector(const multi_type_vector &other)
Copy constructor.
- Parameters
other – the other instance to copy values from.
-
multi_type_vector(multi_type_vector &&other)
Move constructor.
- Parameters
other – the other instance to move values from.
-
~multi_type_vector()
Destructor. It deletes all allocated element blocks.
-
position_type position(size_type pos)
Given the logical position of an element, get the iterator of the block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range, except when the specified position is the position immediately after the last valid position, it will return a valid position object representing the end position.- Parameters
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
position_type position(const iterator &pos_hint, size_type pos)
Given the logical position of an element, get the iterator of the block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range, except when the specified position is the position immediately after the last valid position, it will return a valid position object representing the end position.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the element position.
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
const_position_type position(size_type pos) const
Given the logical position of an element, get an iterator referencing the element block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
const_position_type position(const const_iterator &pos_hint, size_type pos) const
Given the logical position of an element, get an iterator referencing the element block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the element position.
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within the block.
-
iterator transfer(size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
Move elements from one container to another. After the move, the segment where the elements were in the source container becomes empty. When transferring managed elements, this call transfers ownership of the moved elements to the destination container. The moved elements will overwrite any existing elements in the destination range of the receiving container. Transfer of elements within the same container is not allowed.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is greater than or equal to the source container size, or the destination container is not large enough to accommodate the transferred elements.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
dest – destination container to which the elements are to be moved.
dest_pos – position in the destination container to which the elements are to be moved.
- Returns
iterator referencing the block where the moved elements were prior to the transfer.
-
iterator transfer(const iterator &pos_hint, size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
Move elements from one container to another. After the move, the segment where the elements were in the source container becomes empty. When transferring managed elements, this call transfers ownership of the moved elements to the new container. The moved elements will overwrite any existing elements in the destination range of the receiving container. Transfer of elements within the same container is not allowed.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is greater than or equal to the source container size, or the destination container is not large enough to accommodate the transferred elements.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the blocks where the elements to be transferred reside.
start_pos – starting position
end_pos – ending position, inclusive.
dest – destination container to which the elements are to be moved.
dest_pos – position in the destination container to which the elements are to be moved.
- Returns
iterator referencing the block where the moved elements were prior to the transfer.
-
template<typename T>
iterator set(size_type pos, const T &value) Set a value of an arbitrary type to a specified position. The type of the value is inferred from the value passed to this method. The new value will overwrite an existing value at the specified position position if any.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos – position to insert the value to.
value – value to insert.
- Returns
iterator position pointing to the block where the value is inserted.
-
template<typename T>
iterator set(const iterator &pos_hint, size_type pos, const T &value) Set a value of an arbitrary type to a specified position. The type of the value is inferred from the value passed to this method. The new value will overwrite an existing value at the specified position position if any.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the right block to insert the value into. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position to insert the value to.
value – value to insert.
- Returns
iterator position pointing to the block where the value is inserted.
-
template<typename T>
iterator set(size_type pos, const T &it_begin, const T &it_end) Set multiple values of identical type to a range of elements starting at specified position. Any existing values will be overwritten by the new values.
The method will throw an
std::out_of_range
exception if the range of new values would fall outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos – position of the first value of the series of new values being inserted.
it_begin – iterator that points to the begin position of the values being set.
it_end – iterator that points to the end position of the values being set.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator set(const iterator &pos_hint, size_type pos, const T &it_begin, const T &it_end) Set multiple values of identical type to a range of elements starting at specified position. Any existing values will be overwritten by the new values.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first insertion block. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the range of new values would fall outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position of the first value of the series of new values being inserted.
it_begin – iterator that points to the begin position of the values being set.
it_end – iterator that points to the end position of the values being set.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator push_back(const T &value) Append a new value to the end of the container.
- Parameters
value – new value to be appended to the end of the container.
- Returns
iterator position pointing to the block where the value is appended, which in this case is always the last block of the container.
-
iterator push_back_empty()
Append a new empty element to the end of the container.
- Returns
iterator position pointing to the block where the new empty element is appended, which in this case is always the last block of the container.
-
template<typename T>
iterator insert(size_type pos, const T &it_begin, const T &it_end) Insert multiple values of identical type to a specified position. Existing values that occur at or below the specified position will get shifted after the insertion. No existing values will be overwritten by the inserted values.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the new values inserted.
- Parameters
pos – position at which the new values are to be inserted.
it_begin – iterator that points to the begin position of the values being inserted.
it_end – iterator that points to the end position of the values being inserted.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator insert(const iterator &pos_hint, size_type pos, const T &it_begin, const T &it_end) Insert multiple values of identical type to a specified position. Existing values that occur at or below the specified position will get shifted after the insertion. No existing values will be overwritten by the inserted values.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first insertion block. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the new values inserted.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position at which the new values are to be inserted.
it_begin – iterator that points to the begin position of the values being inserted.
it_end – iterator that points to the end position of the values being inserted.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
mtv::element_t get_type(size_type pos) const
Get the type of an element at specified position.
- Parameters
pos – position of the element.
- Returns
element type.
-
bool is_empty(size_type pos) const
Check if element at specified position is empty of not.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to check.
- Returns
true if the element is empty, false otherwise.
-
iterator set_empty(size_type start_pos, size_type end_pos)
Set specified range of elements to be empty. Any existing values will be overwritten.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are emptied.
-
iterator set_empty(const iterator &pos_hint, size_type start_pos, size_type end_pos)
Set specified range of elements to be empty. Any existing values will be overwritten.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first block to empty. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the start position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right blocks to empty.
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are emptied.
-
void erase(size_type start_pos, size_type end_pos)
Erase elements located between specified start and end positions. The end positions are both inclusive. Those elements originally located after the specified end position will get shifted up after the erasure.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container range.Calling this method will decrease the size of the container by the length of the erased range.
- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
-
iterator insert_empty(size_type pos, size_type length)
Insert a range of empty elements at specified position. Those elements originally located after the insertion position will get shifted down after the insertion.
The method will throw an
std::out_of_range
exception if either the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the inserted empty elements.
- Parameters
pos – position at which to insert a range of empty elements.
length – number of empty elements to insert.
- Returns
iterator position pointing to the block where the empty range is inserted. When no insertion occurs because the length is zero, the end iterator position is returned.
-
iterator insert_empty(const iterator &pos_hint, size_type pos, size_type length)
Insert a range of empty elements at specified position. Those elements originally located after the insertion position will get shifted down after the insertion.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the block in which to insert the new empty segment. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the start position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if either the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the inserted empty elements.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block in which to insert the empty segment.
pos – position at which to insert a range of empty elements.
length – number of empty elements to insert.
- Returns
iterator position pointing to the block where the empty range is inserted. When no insertion occurs because the length is zero, the end iterator position is returned.
-
void clear()
Clear the content of the container. The size of the container will become zero after calling this method.
-
size_type block_size() const
Return the current number of blocks in the primary array. Each non-empty block stores a secondary block that stores elements in a contiguous memory region (element block) and the number of elements it stores. An empty block only stores its logical size and does not store an actual element block.
For instance, if the container stores values of double-precision type at rows 0 to 2, values of std::string type at 3 to 7, and empty values at 8 to 10, it would consist of three blocks: one that stores double values, one that stores std::string values, and one that represents the empty value range in this exact order. In this specific scenario,
block_size()
returns 3, andsize()
returns 11.- Returns
current number of blocks in the primary array.
-
bool empty() const
Return whether or not the container is empty.
- Returns
true if the container is empty, false otherwise.
-
template<typename T>
void get(size_type pos, T &value) const Get the value of an element at specified position. The caller must pass a variable of the correct type to store the value.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element value to retrieve.
value – (out) variable to store the retrieved value.
-
template<typename T>
T get(size_type pos) const Get the value of an element at specified position. The caller must specify the type of the element as the template parameter e.g. get<double>(1).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element value to retrieve.
- Returns
element value.
-
template<typename T>
T release(size_type pos) Return the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to release.
- Returns
element value.
-
template<typename T>
iterator release(size_type pos, T &value) Retrieve the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to release.
value – element value.
- Returns
iterator referencing the block where the position of the released element is.
-
template<typename T>
iterator release(const iterator &pos_hint, size_type pos, T &value) Retrieve the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the block where the element resides.
pos – position of the element to release.
value – element value.
- Returns
iterator referencing the block where the position of the released element is.
-
void release()
Release all its elements, and empties its content. Calling this method relinquishes the ownership of all elements stored in managed element blocks if any.
This call is equivalent of clear() if the container consists of no managed element blocks.
-
iterator release_range(size_type start_pos, size_type end_pos)
Make all elements within specified range empty, and relinquish the ownership of the elements in that range. All elements in the managed element blocks within the range will be released and the container will no longer manage their life cycles after the call.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are released.
-
iterator release_range(const iterator &pos_hint, size_type start_pos, size_type end_pos)
Make all elements within specified range empty, and relinquish the ownership of the elements in that range. All elements in the managed element blocks within the range will be released and the container will no longer manage their life cycles after the call.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first block to empty. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right blocks in which elements are to be released.
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are released.
-
const_iterator begin() const
-
const_iterator end() const
-
const_iterator cbegin() const
-
const_iterator cend() const
-
reverse_iterator rbegin()
-
reverse_iterator rend()
-
const_reverse_iterator rbegin() const
-
const_reverse_iterator rend() const
-
const_reverse_iterator crbegin() const
-
const_reverse_iterator crend() const
-
void resize(size_type new_size)
Extend or shrink the container. When extending the container, it appends a series of empty elements to the end. When shrinking, the elements at the end of the container get stripped off.
- Parameters
new_size – size of the container after the resize.
-
void swap(multi_type_vector &other)
Swap the content with another container.
- Parameters
other – another container to swap content with.
-
void swap(size_type start_pos, size_type end_pos, multi_type_vector &other, size_type other_pos)
Swap a part of the content with another instance.
- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
other – another instance to swap the content with.
other_pos – insertion position in the other instance.
-
void shrink_to_fit()
Trim excess capacity from all non-empty blocks.
-
bool operator==(const multi_type_vector &other) const
-
bool operator!=(const multi_type_vector &other) const
-
multi_type_vector &operator=(const multi_type_vector &other)
-
multi_type_vector &operator=(multi_type_vector &&other)
Public Static Functions
-
static position_type next_position(const position_type &pos)
Move the position object to the next logical position. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
- Returns
position object that points to the next logical position.
-
static position_type advance_position(const position_type &pos, int steps)
Increment or decrement the position object by specified steps. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
steps – steps to advance the position object.
- Returns
position object that points to the new logical position.
-
static const_position_type next_position(const const_position_type &pos)
Move the position object to the next logical position. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
- Returns
position object that points to the next logical position.
-
static const_position_type advance_position(const const_position_type &pos, int steps)
Increment or decrement the position object by specified steps. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
steps – steps to advance the position object.
- Returns
position object that points to the new logical position.
-
static size_type logical_position(const const_position_type &pos)
Extract the logical position from a position object.
- Parameters
pos – position object.
- Returns
logical position of the element that the position object references.
-
template<typename _Blk>
static _Blk::value_type get(const const_position_type &pos) Get element value from a position object. The caller must specify the type of block in which the element is expected to be stored.
- Parameters
pos – position object.
- Returns
element value.
mdds::mtv::aos::multi_type_vector
-
template<typename ElemBlockFunc, typename Trait = mdds::mtv::default_trait>
class mdds::mtv::aos::multi_type_vector Multi-type vector consists of a series of one or more blocks, and each block may either be empty, or stores a series of non-empty elements of identical type. These blocks collectively represent a single logical one-dimensional array that may store elements of different types. It is guaranteed that the block types of neighboring blocks are always different.
Structurally, the primary array stores block instances whose types are of
value_type
, which in turn consists of the following data members:type
which indicates the block type,position
which stores the logical position of the first element of the block,size
which stores the logical size of the block, anddata
which stores the pointer to a secondary array (a.k.a. element block) which stores the actual element values, ornullptr
in case the block represents an empty segment.
This variant implements an array-of-structures (AoS) storage.
Public Types
-
typedef size_t size_type
-
typedef mdds::mtv::base_element_block element_block_type
-
typedef ElemBlockFunc element_block_func
-
using event_func = typename Trait::event_func
Optional event handler function structure, whose functions get called at specific events. The following events are currently supported:
element_block_acquired
- this gets called whenever the container acquires a new element block either as a result of a new element block creation or a tranfer of an existing element block from another container.element_block_released
- this gets called whenever the container releases an existing element block either because the block gets deleted or gets transferred to another container.
See also
mdds::mtv::empty_event_func for the precise function signatures of the event handler functions.
-
typedef detail::iterator_base<iterator_trait, itr_forward_update> iterator
-
typedef detail::iterator_base<reverse_iterator_trait, itr_no_update> reverse_iterator
-
typedef detail::const_iterator_base<const_iterator_trait, itr_forward_update, iterator> const_iterator
-
typedef detail::const_iterator_base<const_reverse_iterator_trait, itr_no_update, reverse_iterator> const_reverse_iterator
-
typedef itr_node value_type
value_type is the type of a block stored in the primary array. It consists of the following data members:
type
which indicates the block type,position
which stores the logical position of the first element of the block,size
which stores the logical size of the block, anddata
which stores the pointer to a secondary array (a.k.a. element block) which stores the actual element values, ornullptr
in case the block represents an empty segment.
-
typedef std::pair<const_iterator, size_type> const_position_type
Public Functions
-
const_iterator begin() const
-
const_iterator end() const
-
const_iterator cbegin() const
-
const_iterator cend() const
-
reverse_iterator rbegin()
-
reverse_iterator rend()
-
const_reverse_iterator rbegin() const
-
const_reverse_iterator rend() const
-
const_reverse_iterator crbegin() const
-
const_reverse_iterator crend() const
-
event_func &event_handler()
-
const event_func &event_handler() const
-
multi_type_vector()
Default constructor. It initializes the container with empty size.
-
multi_type_vector(const event_func &hdl)
Constructor that takes an lvalue reference to an event handler object. The event handler instance will be copy-constructed.
- Parameters
hdl – lvalue reference to an event handler object.
-
multi_type_vector(event_func &&hdl)
Constructor that takes an rvalue reference to an event handler object. The event handler instance will be move-constructed.
- Parameters
hdl – rvalue reference to an event handler object.
-
multi_type_vector(size_type init_size)
Constructor that takes initial size of the container. When the size specified is greater than 0, it initializes the container with empty elements.
- Parameters
init_size – initial container size.
-
template<typename T>
multi_type_vector(size_type init_size, const T &value) Constructor that takes initial size of the container and an element value to initialize the elements to. When the size specified is greater than 0, it initializes the container with elements that are copies of the value specified.
- Parameters
init_size – initial container size.
value – initial element value.
-
template<typename T>
multi_type_vector(size_type init_size, const T &it_begin, const T &it_end) Constructor that takes initial size of the container and begin and end iterator positions that specify a series of elements to initialize the container to. The container will contain copies of the elements specified after this call returns.
- Parameters
init_size – initial container size.
it_begin – iterator that points to the begin position of the values the container is being initialized to.
it_end – iterator that points to the end position of the values the container is being initialized to. The end position is not inclusive.
-
multi_type_vector(const multi_type_vector &other)
Copy constructor.
- Parameters
other – the other instance to copy values from.
-
multi_type_vector(multi_type_vector &&other)
Move constructor.
- Parameters
other – the other instance to move values from.
-
~multi_type_vector()
Destructor. It deletes all allocated data blocks.
-
template<typename T>
iterator set(size_type pos, const T &value) Set a value of an arbitrary type to a specified position. The type of the value is inferred from the value passed to this method. The new value will overwrite an existing value at the specified position position if any.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos – position to insert the value to.
value – value to insert.
- Returns
iterator position pointing to the block where the value is inserted.
-
template<typename T>
iterator set(const iterator &pos_hint, size_type pos, const T &value) Set a value of an arbitrary type to a specified position. The type of the value is inferred from the value passed to this method. The new value will overwrite an existing value at the specified position position if any.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the right block to insert the value into. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position to insert the value to.
value – value to insert.
- Returns
iterator position pointing to the block where the value is inserted.
-
template<typename T>
iterator set(size_type pos, const T &it_begin, const T &it_end) Set multiple values of identical type to a range of elements starting at specified position. Any existing values will be overwritten by the new values.
The method will throw an
std::out_of_range
exception if the range of new values would fall outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos – position of the first value of the series of new values being inserted.
it_begin – iterator that points to the begin position of the values being set.
it_end – iterator that points to the end position of the values being set.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator set(const iterator &pos_hint, size_type pos, const T &it_begin, const T &it_end) Set multiple values of identical type to a range of elements starting at specified position. Any existing values will be overwritten by the new values.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first insertion block. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the range of new values would fall outside the current container range.Calling this method will not change the size of the container.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position of the first value of the series of new values being inserted.
it_begin – iterator that points to the begin position of the values being set.
it_end – iterator that points to the end position of the values being set.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator push_back(const T &value) Append a new value to the end of the container.
- Parameters
value – new value to be appended to the end of the container.
- Returns
iterator position pointing to the block where the value is appended, which in this case is always the last block of the container.
-
iterator push_back_empty()
Append a new empty element to the end of the container.
- Returns
iterator position pointing to the block where the new empty element is appended, which in this case is always the last block of the container.
-
template<typename T>
iterator insert(size_type pos, const T &it_begin, const T &it_end) Insert multiple values of identical type to a specified position. Existing values that occur at or below the specified position will get shifted after the insertion. No existing values will be overwritten by the inserted values.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the new values inserted.
- Parameters
pos – position at which the new values are to be inserted.
it_begin – iterator that points to the begin position of the values being inserted.
it_end – iterator that points to the end position of the values being inserted.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
iterator insert(const iterator &pos_hint, size_type pos, const T &it_begin, const T &it_end) Insert multiple values of identical type to a specified position. Existing values that occur at or below the specified position will get shifted after the insertion. No existing values will be overwritten by the inserted values.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first insertion block. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the insertion position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the new values inserted.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block to insert the value into.
pos – position at which the new values are to be inserted.
it_begin – iterator that points to the begin position of the values being inserted.
it_end – iterator that points to the end position of the values being inserted.
- Returns
iterator position pointing to the block where the value is inserted. When no value insertion occurs because the value set is empty, the end iterator position is returned.
-
template<typename T>
void get(size_type pos, T &value) const Get the value of an element at specified position. The caller must pass a variable of the correct type to store the value.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element value to retrieve.
value – (out) variable to store the retrieved value.
-
template<typename T>
T get(size_type pos) const Get the value of an element at specified position. The caller must specify the type of the element as the template parameter e.g. get<double>(1).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element value to retrieve.
- Returns
element value.
-
template<typename T>
T release(size_type pos) Return the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to release.
- Returns
element value.
-
template<typename T>
iterator release(size_type pos, T &value) Retrieve the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to release.
value – element value.
- Returns
iterator referencing the block where the position of the released element is.
-
template<typename T>
iterator release(const iterator &pos_hint, size_type pos, T &value) Retrieve the value of an element at specified position and set that position empty. If the element resides in a managed element block, this call will release that element from that block. If the element is on a non-managed element block, this call is equivalent to set_empty(pos, pos).
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the block where the element resides.
pos – position of the element to release.
value – element value.
- Returns
iterator referencing the block where the position of the released element is.
-
void release()
Release all its elements, and empties its content. Calling this method relinquishes the ownership of all elements stored in managed element blocks if any.
This call is equivalent of clear() if the container consists of no managed element blocks.
-
iterator release_range(size_type start_pos, size_type end_pos)
Make all elements within specified range empty, and relinquish the ownership of the elements in that range. All elements in the managed element blocks within the range will be released and the container will no longer manage their life cycles after the call.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are released.
-
iterator release_range(const iterator &pos_hint, size_type start_pos, size_type end_pos)
Make all elements within specified range empty, and relinquish the ownership of the elements in that range. All elements in the managed element blocks within the range will be released and the container will no longer manage their life cycles after the call.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first block to empty. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right blocks in which elements are to be released.
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are released.
-
position_type position(size_type pos)
Given the logical position of an element, get the iterator of the block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range, except when the specified position is the position immediately after the last valid position, it will return a valid position object representing the end position.- Parameters
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
position_type position(const iterator &pos_hint, size_type pos)
Given the logical position of an element, get the iterator of the block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range, except when the specified position is the position immediately after the last valid position, it will return a valid position object representing the end position.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the element position.
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
const_position_type position(size_type pos) const
Given the logical position of an element, get an iterator referencing the element block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within that block.
-
const_position_type position(const const_iterator &pos_hint, size_type pos) const
Given the logical position of an element, get an iterator referencing the element block where the element is located, and its offset from the first element of that block.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the element position.
pos – logical position of the element.
- Returns
position object that stores an iterator referencing the element block where the element resides, and its offset within the block.
-
iterator transfer(size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
Move elements from one container to another. After the move, the segment where the elements were in the source container becomes empty. When transferring managed elements, this call transfers ownership of the moved elements to the destination container. The moved elements will overwrite any existing elements in the destination range of the receiving container. Transfer of elements within the same container is not allowed.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is greater than or equal to the source container size, or the destination container is not large enough to accommodate the transferred elements.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
dest – destination container to which the elements are to be moved.
dest_pos – position in the destination container to which the elements are to be moved.
- Returns
iterator referencing the block where the moved elements were prior to the transfer.
-
iterator transfer(const iterator &pos_hint, size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
Move elements from one container to another. After the move, the segment where the elements were in the source container becomes empty. When transferring managed elements, this call transfers ownership of the moved elements to the new container. The moved elements will overwrite any existing elements in the destination range of the receiving container. Transfer of elements within the same container is not allowed.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is greater than or equal to the source container size, or the destination container is not large enough to accommodate the transferred elements.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the blocks where the elements to be transferred reside.
start_pos – starting position
end_pos – ending position, inclusive.
dest – destination container to which the elements are to be moved.
dest_pos – position in the destination container to which the elements are to be moved.
- Returns
iterator referencing the block where the moved elements were prior to the transfer.
-
mtv::element_t get_type(size_type pos) const
Get the type of an element at specified position.
- Parameters
pos – position of the element.
- Returns
element type.
-
bool is_empty(size_type pos) const
Check if element at specified position is empty of not.
The method will throw an
std::out_of_range
exception if the specified position is outside the current container range.- Parameters
pos – position of the element to check.
- Returns
true if the element is empty, false otherwise.
-
iterator set_empty(size_type start_pos, size_type end_pos)
Set specified range of elements to be empty. Any existing values will be overwritten.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are emptied.
-
iterator set_empty(const iterator &pos_hint, size_type start_pos, size_type end_pos)
Set specified range of elements to be empty. Any existing values will be overwritten.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the first block to empty. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the start position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container size.- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right blocks to empty.
start_pos – starting position
end_pos – ending position, inclusive.
- Returns
iterator position pointing to the block where the elements are emptied.
-
void erase(size_type start_pos, size_type end_pos)
Erase elements located between specified start and end positions. The end positions are both inclusive. Those elements originally located after the specified end position will get shifted up after the erasure.
The method will throw an
std::out_of_range
exception if either the starting or the ending position is outside the current container range.Calling this method will decrease the size of the container by the length of the erased range.
- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
-
iterator insert_empty(size_type pos, size_type length)
Insert a range of empty elements at specified position. Those elements originally located after the insertion position will get shifted down after the insertion.
The method will throw an
std::out_of_range
exception if either the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the inserted empty elements.
- Parameters
pos – position at which to insert a range of empty elements.
length – number of empty elements to insert.
- Returns
iterator position pointing to the block where the empty range is inserted. When no insertion occurs because the length is zero, the end iterator position is returned.
-
iterator insert_empty(const iterator &pos_hint, size_type pos, size_type length)
Insert a range of empty elements at specified position. Those elements originally located after the insertion position will get shifted down after the insertion.
This variant takes an iterator as an additional parameter, which is used as a block position hint to speed up the lookup of the block in which to insert the new empty segment. The other variant that doesn’t take an iterator always starts the block lookup from the first block, which does not scale well as the block size grows.
This position hint iterator must precede the start position to yield any performance benefit.
The caller is responsible for ensuring that the passed iterator is valid. The behavior of this method when passing an invalid iterator is undefined.
The method will throw an
std::out_of_range
exception if either the specified position is outside the current container range.Calling this method will increase the size of the container by the length of the inserted empty elements.
- Parameters
pos_hint – iterator used as a block position hint, to specify which block to start when searching for the right block in which to insert the empty segment.
pos – position at which to insert a range of empty elements.
length – number of empty elements to insert.
- Returns
iterator position pointing to the block where the empty range is inserted. When no insertion occurs because the length is zero, the end iterator position is returned.
-
void clear()
Clear the content of the container. The size of the container will become zero after calling this method.
-
size_type block_size() const
Return the current number of blocks in the primary array. Each non-empty block stores a secondary block that stores elements in a contiguous region in memory (element block) and the number of elements it stores. An empty block only stores its logical size and does not store an actual element block.
For instance, if the container stores values of double-precision type at rows 0 to 2, values of std::string type at 3 to 7, and empty values at 8 to 10, it would consist of three blocks: one that stores double values, one that stores std::string values, and one that represents the empty value range in this exact order. In this specific scenario,
block_size()
returns 3, andsize()
returns 11.- Returns
current number of blocks in the primary array.
-
bool empty() const
Return whether or not the container is empty.
- Returns
true if the container is empty, false otherwise.
-
void resize(size_type new_size)
Extend or shrink the container. When extending the container, it appends a series of empty elements to the end. When shrinking, the elements at the end of the container get stripped off.
- Parameters
new_size – size of the container after the resize.
-
void swap(multi_type_vector &other)
Swap the content with another container.
- Parameters
other – another container to swap content with.
-
void swap(size_type start_pos, size_type end_pos, multi_type_vector &other, size_type other_pos)
Swap a part of the content with another instance.
- Parameters
start_pos – starting position
end_pos – ending position, inclusive.
other – another instance to swap the content with.
other_pos – insertion position in the other instance.
-
void shrink_to_fit()
Trim excess capacity from all non-empty blocks.
-
bool operator==(const multi_type_vector &other) const
-
bool operator!=(const multi_type_vector &other) const
-
multi_type_vector &operator=(const multi_type_vector &other)
-
multi_type_vector &operator=(multi_type_vector &&other)
Public Static Functions
-
static position_type next_position(const position_type &pos)
Move the position object to the next logical position. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
- Returns
position object that points to the next logical position.
-
static position_type advance_position(const position_type &pos, int steps)
Increment or decrement the position object by specified steps. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
steps – steps to advance the position object.
- Returns
position object that points to the new logical position.
-
static const_position_type next_position(const const_position_type &pos)
Move the position object to the next logical position. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
- Returns
position object that points to the next logical position.
-
static const_position_type advance_position(const const_position_type &pos, int steps)
Increment or decrement the position object by specified steps. Caller must ensure the the position object is valid.
- Parameters
pos – position object.
steps – steps to advance the position object.
- Returns
position object that points to the new logical position.
-
static size_type logical_position(const const_position_type &pos)
Extract the logical position from a position object.
- Parameters
pos – position object.
- Returns
logical position of the element that the position object references.
-
template<typename Blk>
static Blk::value_type get(const const_position_type &pos) Get element value from a position object. The caller must specify the type of block in which the element is expected to be stored.
- Parameters
pos – position object.
- Returns
element value.
mdds::mtv::empty_event_func
-
struct mdds::mtv::empty_event_func
Empty event function handler structure, used when no custom function handler is specified.
Public Functions
-
inline void element_block_acquired(const base_element_block *block)
Callback function for element block acquisition events. This gets called whenever the container acquires a new element block either as a result of a new element block creation or a transfer of an existing element block from another container.
- Parameters
block – pointer to the acquired element block instance.
-
inline void element_block_released(const base_element_block *block)
Callback function for element block release events. This gets called whenever the container releases an existing element block either because the block is about to be deleted or to be transferred to another container.
- Parameters
block – pointer to the element block instance being released.
-
inline void element_block_acquired(const base_element_block *block)
mdds::mtv::default_trait
-
struct mdds::mtv::default_trait
Default trait to be used when no custom trait is specified.
Public Types
-
using event_func = empty_event_func
Class or struct type that contains callback functions for element block events as its member functions.
Public Static Attributes
-
static constexpr lu_factor_t loop_unrolling = lu_factor_t::lu16
Static value specifying the loop-unrolling factor to use for the block position adjustment function. This must be a const expression.
-
using event_func = empty_event_func
Element Blocks
-
class base_element_block
Non-template common base type necessary for blocks of all types to be stored in a single container.
Subclassed by mdds::mtv::element_block< _Self, _TypeId, _Data >
-
template<typename _Self, element_t _TypeId, typename _Data>
class mdds::mtv::element_block : public mdds::mtv::base_element_block Subclassed by mdds::mtv::copyable_element_block< default_element_block< _TypeId, _Data >, _TypeId, _Data >, mdds::mtv::copyable_element_block< managed_element_block< _TypeId, _Data >, _TypeId, _Data * >, mdds::mtv::noncopyable_element_block< noncopyable_managed_element_block< _TypeId, _Data >, _TypeId, _Data * >, mdds::mtv::copyable_element_block< _Self, _TypeId, _Data >, mdds::mtv::noncopyable_element_block< _Self, _TypeId, _Data >
Public Types
-
typedef store_type::iterator iterator
-
typedef store_type::reverse_iterator reverse_iterator
-
typedef store_type::const_iterator const_iterator
-
typedef store_type::const_reverse_iterator const_reverse_iterator
Public Functions
Public Static Functions
-
static inline const value_type &at(const base_element_block &block, typename store_type::size_type pos)
-
static inline value_type &at(base_element_block &block, typename store_type::size_type pos)
-
static inline value_type *data(base_element_block &block)
-
static inline store_type::size_type size(const base_element_block &block)
-
static inline iterator begin(base_element_block &block)
-
static inline iterator end(base_element_block &block)
-
static inline const_iterator begin(const base_element_block &block)
-
static inline const_iterator end(const base_element_block &block)
-
static inline const_iterator cbegin(const base_element_block &block)
-
static inline const_iterator cend(const base_element_block &block)
-
static inline reverse_iterator rbegin(base_element_block &block)
-
static inline reverse_iterator rend(base_element_block &block)
-
static inline const_reverse_iterator rbegin(const base_element_block &block)
-
static inline const_reverse_iterator rend(const base_element_block &block)
-
static inline const_reverse_iterator crbegin(const base_element_block &block)
-
static inline const_reverse_iterator crend(const base_element_block &block)
-
static inline _Self &get(base_element_block &block)
-
static inline const _Self &get(const base_element_block &block)
-
static inline void set_value(base_element_block &blk, size_t pos, const _Data &val)
-
static inline void get_value(const base_element_block &blk, size_t pos, _Data &val)
-
static inline value_type get_value(const base_element_block &blk, size_t pos)
-
static inline void append_value(base_element_block &blk, const _Data &val)
-
static inline void prepend_value(base_element_block &blk, const _Data &val)
-
static inline void delete_block(const base_element_block *p)
-
static inline void resize_block(base_element_block &blk, size_t new_size)
-
static inline void print_block(const base_element_block&)
-
static inline void erase_block(base_element_block &blk, size_t pos)
-
static inline void erase_block(base_element_block &blk, size_t pos, size_t size)
-
static inline void append_values_from_block(base_element_block &dest, const base_element_block &src)
-
static inline void append_values_from_block(base_element_block &dest, const base_element_block &src, size_t begin_pos, size_t len)
-
static inline void assign_values_from_block(base_element_block &dest, const base_element_block &src, size_t begin_pos, size_t len)
-
static inline void prepend_values_from_block(base_element_block &dest, const base_element_block &src, size_t begin_pos, size_t len)
-
static inline void swap_values(base_element_block &blk1, base_element_block &blk2, size_t pos1, size_t pos2, size_t len)
-
template<typename _Iter>
static inline void set_values(base_element_block &block, size_t pos, const _Iter &it_begin, const _Iter &it_end)
-
template<typename _Iter>
static inline void append_values(base_element_block &block, const _Iter &it_begin, const _Iter &it_end)
-
template<typename _Iter>
static inline void prepend_values(base_element_block &block, const _Iter &it_begin, const _Iter &it_end)
-
template<typename _Iter>
static inline void assign_values(base_element_block &dest, const _Iter &it_begin, const _Iter &it_end)
-
template<typename _Iter>
static inline void insert_values(base_element_block &block, size_t pos, const _Iter &it_begin, const _Iter &it_end)
-
static inline size_t capacity(const base_element_block &block)
-
static inline void shrink_to_fit(base_element_block &block)
-
typedef store_type::iterator iterator
-
template<element_t _TypeId, typename _Data>
struct mdds::mtv::default_element_block : public mdds::mtv::copyable_element_block<default_element_block<_TypeId, _Data>, _TypeId, _Data> Template for default, unmanaged element block for use in multi_type_vector.
Public Types
-
typedef copyable_element_block<default_element_block, _TypeId, _Data> base_type
-
typedef default_element_block<_TypeId, _Data> self_type
-
typedef copyable_element_block<default_element_block, _TypeId, _Data> base_type
-
template<typename _Self, element_t _TypeId, typename _Data>
class mdds::mtv::copyable_element_block : public mdds::mtv::element_block<_Self, _TypeId, _Data> Public Static Functions
-
static inline _Self *clone_block(const base_element_block &blk)
-
static inline _Self &get(base_element_block &block)
-
static inline const _Self &get(const base_element_block &block)
-
static inline _Self *clone_block(const base_element_block &blk)
-
template<typename _Self, element_t _TypeId, typename _Data>
class mdds::mtv::noncopyable_element_block : public mdds::mtv::element_block<_Self, _TypeId, _Data> Public Functions
-
noncopyable_element_block(const noncopyable_element_block&) = delete
-
noncopyable_element_block &operator=(const noncopyable_element_block&) = delete
Public Static Functions
-
static inline _Self *clone_block(const base_element_block&)
-
noncopyable_element_block(const noncopyable_element_block&) = delete
-
template<element_t _TypeId, typename _Data>
struct mdds::mtv::managed_element_block : public mdds::mtv::copyable_element_block<managed_element_block<_TypeId, _Data>, _TypeId, _Data*> Template for element block that stores pointers to objects whose life cycles are managed by the block.
Public Types
-
typedef copyable_element_block<managed_element_block<_TypeId, _Data>, _TypeId, _Data*> base_type
-
typedef managed_element_block<_TypeId, _Data> self_type
Public Functions
-
inline managed_element_block()
-
inline managed_element_block(size_t n)
-
inline managed_element_block(const managed_element_block &r)
-
inline ~managed_element_block()
-
typedef copyable_element_block<managed_element_block<_TypeId, _Data>, _TypeId, _Data*> base_type
-
template<element_t _TypeId, typename _Data>
struct mdds::mtv::noncopyable_managed_element_block : public mdds::mtv::noncopyable_element_block<noncopyable_managed_element_block<_TypeId, _Data>, _TypeId, _Data*> Public Types
-
typedef noncopyable_element_block<noncopyable_managed_element_block<_TypeId, _Data>, _TypeId, _Data*> base_type
-
typedef managed_element_block<_TypeId, _Data> self_type
Public Functions
-
inline noncopyable_managed_element_block()
-
inline noncopyable_managed_element_block(size_t n)
-
template<typename _Iter>
inline noncopyable_managed_element_block(const _Iter &it_begin, const _Iter &it_end)
-
inline ~noncopyable_managed_element_block()
-
typedef noncopyable_element_block<noncopyable_managed_element_block<_TypeId, _Data>, _TypeId, _Data*> base_type
-
struct element_block_func : public mdds::mtv::element_block_func_base
Default cell block function definitions. Implementation can use this if it only uses the default block types implemented by the library.
Types
mdds::mtv::element_t
-
using mdds::mtv::element_t = int
mdds::mtv::lu_factor_t
-
enum class mdds::mtv::lu_factor_t : int
Loop-unrolling factor with optional SIMD feature.
In each enumerator value, the first byte contains the loop-unrolling factor (either 0, 4, 8, 16 or 32), while the second byte stores SIMD flags.
Values:
-
enumerator none
-
enumerator lu4
-
enumerator lu8
-
enumerator lu16
-
enumerator lu32
-
enumerator sse2_x64
-
enumerator sse2_x64_lu4
-
enumerator sse2_x64_lu8
-
enumerator sse2_x64_lu16
-
enumerator avx2_x64
-
enumerator avx2_x64_lu4
-
enumerator avx2_x64_lu8
-
enumerator none
mdds::mtv::trace_method_t
-
enum class mdds::mtv::trace_method_t : int
Type of traced method.
An
accessor
in this context is a method whose call alone does not mutate the state of the container. All const methods are accessors. Note that some non-const methods that return non-const references to internal data are still considered accessors.A
mutator
is a method that, when called, may change the state of the stored data immediately.The
accessor_with_pos_hint
label signifies an accessor that takes a position hint as its first argument. Likewise,mutator_with_pos_hint
signifies a mutator that takes a position hint as its first argument.The
constructor
anddestructor
labels are hopefully self-explanatory.Values:
-
enumerator unspecified
-
enumerator accessor
-
enumerator accessor_with_pos_hint
-
enumerator mutator
-
enumerator mutator_with_pos_hint
-
enumerator constructor
-
enumerator destructor
-
enumerator unspecified
mdds::mtv::trace_method_properties_t
-
struct mdds::mtv::trace_method_properties_t
Struct containing the information about each traced method.
Public Members
-
trace_method_t type = trace_method_t::unspecified
-
const void *instance = nullptr
Memory address of the container instance the traced method belongs to. This is essentially the
this
pointer inside the traced method.
-
const char *function_name = nullptr
Name of the method.
-
std::string function_args
String containing the argument names as well as their values if available.
-
const char *filepath = nullptr
Path of the file where the method body is.
-
int line_number = -1
Line number of the first line of the traced method body.
-
trace_method_t type = trace_method_t::unspecified
Exceptions
-
class mdds::mtv::element_block_error : public mdds::general_error
Generic exception used for errors specific to element block operations.
Public Functions
-
inline element_block_error(const std::string &msg)
-
inline element_block_error(const std::string &msg)
Collection
-
template<typename _MtvT>
class mdds::mtv::collection Special-purpose collection of multiple multi_type_vector instances to allow them to be traversed “sideways” i.e. orthogonal to the direction of the vector instances. All involved multi_type_vector instances must be of the same type and length.
Public Types
Public Functions
-
collection()
-
template<typename _T>
collection(const _T &begin, const _T &end) Constructor that takes the start and end iterators of the multi_type_vector instances to reference in the collection.
- Parameters
begin – iterator that references the first multi_type_vector instance to place in the collection.
end – iterator that references the position past the last multi_type_vector instance to place in the collection.
-
const_iterator begin() const
Return an iterator that references the first element in the collection.
- Returns
iterator that references the first element in the collection.
-
const_iterator end() const
Return an iterator that references the position past the last element in the collection.
- Returns
iterator that references the position past the last element in the collection.
-
size_type size() const
Return the length of the vector instances stored in the collection. This will be equivalent of the length of each multi_type_vector instance, since all stored instances have the same length.
- Returns
length of the stored multi_type_vector instances.
-
void swap(collection &other)
Swap the entire collection with another collection instance.
- Parameters
other – another collection instance to swap contents with.
-
void set_collection_range(size_type start, size_type size)
Set the sub-range of the collection to iterate through.
For instance, if the collection consists of 100 multi_type_vector instances, and you want to iterate through only 50 of them starting from the second instance, you set the start index to 1 (as it’s 0-based), and the size to 50.
- Parameters
start – 0-based index of the first multi_type_vector instance to iterate through.
size – length of the collection range i.e. the number of vector instances to iterate through starting from the specified first vector instance.
-
void set_element_range(size_type start, size_type size)
Set the sub element range to iterate through. This limits the element range in each multi_type_vector instance to iterate through. The direction of the element range is orthogonal to the direction of the collection range.
For instance, if the collection consists of multiple multi_type_vector instances all of which have a length of 50, and you only wish to iterate from the 3rd element through the 10th element in each vector instance, then you set the start index to 2 and the size to 8.
- Parameters
start – 0-based index of the starting element position.
size – length of the element range to iterate through starting from the specified start element position.
-
collection()