Page MenuHomePhorge

No OneTemporary

Size
29 KB
Referenced Files
None
Subscribers
None
diff --git a/examples/CSVFiles/main.cpp b/examples/CSVFiles/main.cpp
index bd8b61b..167e9db 100644
--- a/examples/CSVFiles/main.cpp
+++ b/examples/CSVFiles/main.cpp
@@ -1,345 +1,347 @@
//===-- examples/CSVFiles/main.cpp ------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/basic-system/basic-system.cpp
///
/// \author Edwin Willegger (edwin.willegger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief A simple example on the basic \c rosa::csv, \c rosa::iterator and
/// \c rosa::writer classes. Focus is on the tuple impementations.
///
//===----------------------------------------------------------------------===//
#include <cstdint>
#include <cstddef>
#include <iostream>
#include <istream>
#include <sstream>
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
#include <typeinfo>
#include <map>
#include <algorithm>
#include <tuple>
#include <type_traits>
#include <unistd.h>
//includes for an complete example to read and write
//with sensors and agents.
#include "rosa/deluxe/DeluxeContext.hpp"
#include "rosa/config/version.h"
//includes to test the basic functionality
//to read and write tuples.
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include "rosa/support/iterator/split_tuple_iterator.hpp"
#include "rosa/support/writer/split_tuple_writer.hpp"
/// the name of the example
const std::string ExampleName = "csvfiles";
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 10;
/// Paths for the CSV files for simulation.
/// input csv files
const std::string csvPath = "../examples/CSVFiles/";
const std::string csvFileWithHeader = csvPath + "HR-New.csv";
const std::string csvFileNoHeader = csvPath + "HR.csv";
const std::string csvFileHeaderSemi = csvPath + "HR-New-Semicolon.csv";
/// output csv files
const std::string csvFileWriteHea = csvPath + "csvwriter_noheader.csv";
const std::string csvFileWriteNoHeaSplit = csvPath + "csvSplitwriter_noheader.csv";
using namespace rosa;
///
/// This function tests the basic CSVIterator capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVReader(void){
//different streams to get the csv data out of the files
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_2(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_3(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_4(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_5(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_6(csvFileWithHeader);
//file contains no header an valid data entries, delimter = ','
std::ifstream file2(csvFileNoHeader);
//file contains header and valid data entries, delimter = ';'
std::ifstream file3(csvFileHeaderSemi);
csv::CSVIterator<int, std::string, std::string, int, int> it(file_header_data);
it.setDelimeter(',');
it++;
it++;
//if you iterate over the end of file, the last values
//of the file will remain in the data structure but no
//error occurs.
it++;
it++;
//-------------------------------------------------------------------
// a possiblity to get the data out of the iterator
std::tuple<int, std::string, std::string, int, int> value = *it;
//
// Show the value of one iterator
//
LOG_INFO( "Values are: ");
LOG_INFO(std::get<0>(value) );
LOG_INFO(std::get<1>(value) );
//--------------------------------------------------------------------
//testing differnet parameters to the constructor
//uncomment to see that it is not possible to iterate over an vector in the tuple.
//rosa::csv::CSVIterator<double, std::vector<int>> it2(file, 1);
//try to skip a valid number of lines after the header
csv::CSVIterator<double, float, int, int, float> it2_0(file_header_data_2, 1);
//try to skip a valid number of lines after the header, but you assume that the file has no header
//uncomment this line to crash the programm
//csv::CSVIterator<double, float, int, int, float> it2_1(file_header_data_3, 0, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines after the header, but you assume that the file has no header
//uncomment this line to crash the program
//csv::CSVIterator<double, float, int, int, float> it2_2(file_header_data_4, 1, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines of a file without header
csv::CSVIterator<double, float, int, int, float> it2_3(file2, 1, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines after the header, but with different delimeter
csv::CSVIterator<double, float, int, int, float> it2_4(file3, 2, csv::HeaderInformation::HasHeader, ';');
// if you skip more lines than valid, you generate an infinte loop
//csv::CSVIterator<double, float, int, int, float> it3(file_header_data_5, 500);
//if you don't need data from all columns just select the number of columns you
//need. You get the data back from the first column (index 0) to the fourth column
//all values from the fifth column are ignored.
csv::CSVIterator<double, float, int, float> it4(file_header_data_6);
}
///
/// This function tests the basic CSVTupleWriter capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVWriter(void){
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteHea);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
//
// Create test tuples
//
std::tuple<int, float, std::string> values(5, 8.3, "hallo");
std::tuple<int, float, std::string> values2(3, 8.3, "end");
//
// Create test header lines for the test tuples
//
std::array<std::string, 3> header {"zero column", "first column", "second column"};
std::array<std::string, 4> headerWrong {"zero column", "first column", "second column", "third column"};
std::array<std::string, 2> headerWrongShort {"zero column", "first column"};
wri.writeHeader(header);
wri.write(values);
wri.write(values);
wri.write(values);
wri << values;
wri << values2;
//uncomment this line to see, that you can't write a header with the too many elements.
//wri.writeHeader(headerWrong);
//uncomment this line to see, that you can't write a header with the too few elements.
//wri.writeHeader(headerWrongShort);
}
///
/// This function tests the basic splitTupleIterator capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVIterator in separate parts.
///
void testsplitTupleIterator(void)
{
//
// Create deluxe context
//
std::unique_ptr<rosa::deluxe::DeluxeContext> C =
deluxe::DeluxeContext::create(ExampleName);
//
// Create deluxe sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
// Three different sensors were created, this is just a random number taken.
AgentHandle Elem0Sensor = C->createSensor<int>("Element1 Sensor");
AgentHandle Elem1Sensor = C->createSensor<float>("Element2 Sensor");
AgentHandle Elem2Sensor = C->createSensor<std::string>("Element3 Sensor");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
// Type aliases for iterators
using Iterator = rosa::csv::CSVIterator<int, float, std::string>;
using IteratorValue = std::tuple<int, float, std::string>;
static_assert (std::is_same<typename Iterator::value_type, IteratorValue>::value, "Iterator must provide tuples" );
//
// Open CSV file and register the columns to the corresponding sensors.
//
std::ifstream TestCSV(csvFileWithHeader);
//
// Test data looks like:
// Element1, Element2, Element3, Element4, Element5 -- is the header line
// 3, 5, 8, 9.5, 17 -- first line of values
// 100, -8, 30, 18.8, 29 -- other line of values were also in the file
// 5, 20, -100, -200.1, -30 -- if you have less number of values than simulation rounds all values
// -- beyond your last value will be zero.
//get element iterator ranges
auto [Elem0Range, Elem1Range, Elem2Range] = iterator::splitTupleIterator(Iterator(TestCSV), Iterator());
- //dissect ranges into begin and end iterators by structred bindings
+ //dissect a range into begin and end iterators by structred bindings
auto[Elem0Begin, Elem0End] = Elem0Range;
- auto[Elem1Begin, Elem1End] = Elem1Range;
- auto[Elem2Begin, Elem2End] = Elem2Range;
+ //deissect a range with functions
+ auto Elem1Begin = iterator::begin(Elem1Range);
+ auto Elem1End = iterator::end(Elem1Range);
C->registerSensorValues(Elem0Sensor, std::move(Elem0Begin), Elem0End);
C->registerSensorValues(Elem1Sensor, std::move(Elem1Begin), Elem1End);
- C->registerSensorValues(Elem2Sensor, std::move(Elem2Begin), Elem2End);
+ C->registerSensorValues(Elem2Sensor, std::move(iterator::begin(Elem2Range)),
+ iterator::end(Elem2Range));
//
// Simulate.
//
C->simulate(NumberOfSimulationCycles);
}
///
/// This function tests the basic splitTupleWriter capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVWriter in separate parts.
///
void testsplitTupleWriter(void){
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteNoHeaSplit);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
// if you omit, the type definition in the template, than auto generated types were used,
// and they may not fit to the used CSVTupleWriter.
wri << std::make_tuple<int, float, std::string>(1000, 50.6, "tuple_created");
auto [T0Writer, T1Writer, T2Writer] = writer::splitTupleWriter(std::move(wri),
writer::IncompleteTuplePolicy::Ignore);
//writing elements in sequential order into the writer classes, but you can write the values into the writers in
//a random order.
T0Writer << (500);
T1Writer << (3.0);
T2Writer << "splitted writter";
T2Writer << "splitting is cool";
T0Writer << (-30);
T1Writer << (-0.004);
// you can also write more often values into a writer and later into the other writers
// all data will be processed correctly into the right order.
T0Writer << (1);
T0Writer << (2);
T1Writer << (-0.4);
T0Writer << (3);
T2Writer << "again";
T0Writer << (4);
T1Writer << (-0.1);
T1Writer << (-0.2);
T2Writer << "and";
T1Writer << (-0.3);
T2Writer << "splitting";
T2Writer << "once again";
// again writing data of one tuple entry to the different writers in a random fashion.
T1Writer << (-0.004);
T2Writer << "splitting is cool";
T0Writer << (-30);
}
int main(void){
LOG_INFO_STREAM << library_string() << " -- " << terminal::Color::Red
<< ExampleName << " example" << terminal::Color::Default << '\n';
//
// Testing CSVWriter.
//
LOG_INFO("Testing CSVWriter CSVTupleItrator implementation: ");
testtupleCSVWriter();
//
// Testing CSVReader.
//
LOG_INFO("Testing CSVReader CSVTupleIterator implementation: ");
testtupleCSVReader();
//
// Testing SplitTupleIterator.
//
LOG_INFO("Testing SplitTupleIterator: ");
testsplitTupleIterator();
//
// Testing SplitTupleWriter.
//
LOG_INFO("Testing SplitTupleWriter: ");
testsplitTupleWriter();
//
// info that user knows programm has finished.
//
LOG_INFO( "All tests finished.");
return 0;
}
diff --git a/include/rosa/support/iterator/split_tuple_iterator.hpp b/include/rosa/support/iterator/split_tuple_iterator.hpp
index 3d1b9e9..f5af821 100644
--- a/include/rosa/support/iterator/split_tuple_iterator.hpp
+++ b/include/rosa/support/iterator/split_tuple_iterator.hpp
@@ -1,431 +1,469 @@
//===-- rosa/support/iterator/split_tuple_iterator.hpp ----------*- C++ -*-===/
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===/
///
/// \file rosa/support/iterator/split_tuple_iterator.hpp
///
/// \authors David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Facilities to split iterators of \c std::tuple into iterators of
/// their elements.
///
//===----------------------------------------------------------------------===/
#ifndef ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP
#define ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP
#include "rosa/support/debug.hpp"
#include "rosa/support/sequence.hpp"
#include <memory>
#include <tuple>
#include <type_traits>
#include <queue>
namespace rosa {
namespace iterator {
/// Anonymous namespace providing implementation for splitting tuple iterators;
/// consider it private.
namespace {
/// Iterator of values provided by a buffer based on an index
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
///
/// \note \p TB is expected to implemnet an interface matching that of \c
/// TupleIteratorBuffer.
template <typename TB, size_t I>
class SplittedElementIterator {
public:
/// Type alias for the values the iterator iterates.
using T = typename TB::template element_type<I>;
/// \defgroup SplittedElementIteratorTypedefs Typedefs of
/// \c SplittedElementIterator
///
/// Standard `typedef`s for iterators.
///
///@{
typedef std::input_iterator_tag
iterator_category; ///< Category of the iterator.
typedef T value_type; ///< Type of values iterated over.
typedef std::size_t difference_type; ///< Type to identify distance.
typedef T *pointer; ///< Pointer to the type iterated over.
typedef T &reference; ///< Reference to the type iterated ver.
///@}
/// Creates a new instance.
///
/// \param Buffer buffer providing values for \p this object
///
/// \note \p Buffer is captured as a \c std::shared_ptr because it is shared
/// among iterators for its element positions.
SplittedElementIterator(std::shared_ptr<TB> Buffer)
: Buffer(Buffer), Value() {
// \c Value is initialized empty so the first incrementation here will read
// the first value.
++(*this);
}
/// Creates an empty new instance.
SplittedElementIterator(void) noexcept : Buffer(), Value() {}
/// Pre-increment operator.
///
/// The implementation reads the next value from \c Buffer. If no more values
/// can be provided by \c Buffer, \p this object becomes empty and the
/// operator has no further effect.
///
/// \return \p this object after incrementing it.
SplittedElementIterator &operator++() {
if (Buffer->template hasMore<I>()) {
Value = Buffer->template next<I>();
} else {
// Reached end of range, remove reference of \c Buffer.
Buffer.reset();
}
return *this;
}
/// Post-increment operator.
///
/// The implementation uses the pre-increment operator and returns a copy of
/// the original state of \p this object.
///
/// \return \p this object before incrementing it.
SplittedElementIterator operator++(int) {
SplittedElementIterator<TB, I> Tmp(*this);
++(*this);
return Tmp;
}
/// Returns a constant reference to the current value.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant reference to the current value.
const T &operator*(void)const noexcept { return Value; }
/// Returns a constant pointer to the current value.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant pointer to the current value.
const T *operator->(void)const noexcept { return &Value; }
/// Tells if \p this object is equal to another one.
///
/// Two \c SplittedElementIterator instances are equal if and only if they are
/// the same or both are empty.
///
/// \param RHS other object to compare to
///
/// \return whether \p this object is equal with \p RHS
bool operator==(const SplittedElementIterator &RHS) const noexcept {
return ((this == &RHS) || (!Buffer && !RHS.Buffer));
}
/// Tells if \p this object is not equal to another one.
///
/// \see SplittedElementIterator::operator==
///
/// \param RHS other object to compare to
///
/// \return whether \p this object is not equal with \p RHS.
bool operator!=(const SplittedElementIterator &RHS) const noexcept {
return !((*this) == RHS);
}
private:
std::shared_ptr<TB> Buffer; ///< Buffer providing values for \p this object
T Value; ///< The current value of the iterator
};
///\defgroup TupleBufferContainer Type converter turning a \c std::tuple of
///types into a \c std::tuple of container of those types.
///
/// The new type is used for buffering elements of tuples separately.
///
///@{
/// Template declaration.
///
/// \tparam T type to convert
///
/// \note The template is defined only when \p T is a \c std::tuple.
///
/// Usage for a type \c Tuple as:\code
/// typename TupleBufferContainer<Tuple>::Type
/// \endcode
template <typename T> struct TupleBufferContainer;
/// Template definition for \c std::tuple.
template <typename... Ts> struct TupleBufferContainer<std::tuple<Ts...>> {
/// The converted type.
using Type = std::tuple<std::queue<Ts>...>;
};
///@}
/// Convenience template type alias for easy use of \c TupleBufferContainer.
///
/// Converts a \c std::tuple of types into a \c std::tuple of container of those
/// types.
///
/// \tparam Tuple type to convert
template <typename Tuple>
using tuple_buffer_container_t = typename TupleBufferContainer<Tuple>::Type;
/// Buffer for element values for iterator of \c std::tuple.
///
/// The class can be instantiated with a range of iterator of \c std::tuple and
/// provides an interface for accessing elements of the iterated tuples one by
/// one.
///
/// \note The class is utilized by \c SplittedElementIterator.
///
/// \tparam TupleIterator the iterator type that provides values of \c
/// std::tuple
///
/// \todo Consider thread safety of the class.
template <typename TupleIterator>
class TupleIteratorBuffer {
public:
/// Type alias for the value type of \p TupleIterator.
/// \note The type is expected to be \c std::tuple.
using iterator_value_type = typename TupleIterator::value_type;
/// The number of elements of \c iterator_value_type.
static constexpr size_t iterator_value_size =
std::tuple_size_v<iterator_value_type>;
/// Template type alias to get element types of \c iterator_value_type by
/// index.
/// \tparam I the index of the element
template <size_t I>
using element_type =
typename std::tuple_element<I, iterator_value_type>::type;
/// Type alias for index sequence for accessing elements of \c
/// iterator_value_type.
using element_idx_seq_t = seq_t<iterator_value_size>;
/// Creates a new instance.
///
/// \param Begin the beginning of the iterator range to buffer
/// \param End the end of the iterator range to buffer
TupleIteratorBuffer(TupleIterator &&Begin, const TupleIterator &End) noexcept
: Iterator(Begin), End(End), Buffer() {}
/// Tells whether there is any more value in the handled range for index \p I.
///
/// \tparam I the index of the element to check
///
/// \return whether there is more value for index \p I
template <size_t I> bool hasMore(void) const noexcept {
const auto &ElementBuffer = std::get<I>(Buffer);
// There is more value if some has already been buffered or the end of the
// handled range is not reached yet.
return !ElementBuffer.empty() || Iterator != End;
}
/// Gives the next value from the handled range for index \p I.
///
/// \note The function should not be called if there is no more value for
/// index \p I (i.e., \c hasMore<I>() returns \c false). If it is called in
/// that situation, it returns the default value of \c element_type<I>.
///
/// \tparam I the index of the element to fetch next value for
///
/// \return the next value for index \p I
template <size_t I> element_type<I> next(void) noexcept {
auto &ElementBuffer = std::get<I>(Buffer);
if (ElementBuffer.empty()) {
// This position needs a new value from Iterator if there is more.
if (Iterator != End) {
// Push next value for all elements.
push(*Iterator++, element_idx_seq_t());
} else {
// No more values; called when hasMore<I>() is false.
// Return default value.
return element_type<I>();
}
}
// Buffer is not empty here, return the next value.
ASSERT(!ElementBuffer.empty() && "Unexpected condition");
// Get the next value and also pop it from the buffer.
const element_type<I> Elem = ElementBuffer.front();
ElementBuffer.pop();
return Elem;
}
private:
/// Buffers next tuple value elementwise into element containers.
///
/// \tparam S0 indices for accessing elements of \c std::tuple
///
/// \param Tuple the values to buffer
///
/// \note The second parameter provides indices as template parameter \p S0
/// and its actual value is ignored.
template <size_t... S0>
void push(const iterator_value_type &Tuple, Seq<S0...>) noexcept {
(std::get<S0>(Buffer).push(std::get<S0>(Tuple)), ...);
}
TupleIterator Iterator; ///< Current input iterator
const TupleIterator End; ///< End of iterator range to handle
tuple_buffer_container_t<iterator_value_type>
Buffer; ///< Container for elementwise buffering
};
/// Template type alias for iterator of an element based on buffered iterator of
/// \c std::tuple.
///
/// The alias utilizes \c SplittedElementIterator for iterating over the values
/// provided by \p TB.
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
template <typename TB, size_t I>
using element_iterator_t = SplittedElementIterator<TB, I>;
/// Template type alias for iterator-range of an element based on buffered
/// iterator of \c std::tuple.
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
template <typename TB, size_t I>
using element_iterator_range_t =
std::pair<element_iterator_t<TB, I>, element_iterator_t<TB, I>>;
///\defgroup ElementIteratorRanges Type converter turning a buffer of \c
/// std::tuple into a \c std::tuple of corresponding \c
/// element_iterator_range_t.
///
///@{
/// Template declaration.
///
/// \tparam TB buffer providing values
/// \tparam S type providing indices for accessing elements of \c std::tuple
///
/// \note \p TB is expected to implement an interface matching that of \c
/// TupleIteratorBuffer.
///
/// \note The template is defined only when \p S is a \c rosa::Seq.
///
/// Usage for a proper buffer type \c TB:\code
/// typename ElementIteratorRanges<TB, typename TB::element_idx_seq_t>::Type
/// \endcode
template <typename TB, typename S> struct ElementIteratorRanges;
/// Template definition.
template <typename TB, size_t... S0>
struct ElementIteratorRanges<TB, Seq<S0...>> {
/// The converted type.
using Type = std::tuple<element_iterator_range_t<TB, S0>...>;
};
///@}
/// Convenience template type alias for easy use of \c ElementIteratorRanges.
///
/// Converts a buffer of \c std::tuple into a \c std::tuple of corresponding \c
/// element_iterator_range_t.
///
/// \tparam TB buffer providing values
///
/// \note \p TB is expected to implement an interface matching that of \c
/// TupleIteratorBuffer.
template <typename TB>
using element_iterator_ranges_t =
typename ElementIteratorRanges<TB, typename TB::element_idx_seq_t>::Type;
/// Template type alias for turning an iterator of \c std::tuple into
/// corresponding \c element_iterator_ranges_t.
///
/// The alias utilizes \c TupleIteratorBuffer for buffering the values provided
/// by \p TupleIterator. The elementwise iterators are \c
/// SplittedElementIterator.
///
/// \tparam TupleIterator iterator of \c std::tuple
template <typename TupleIterator>
using splitted_tuple_iterator_ranges_t =
element_iterator_ranges_t<TupleIteratorBuffer<TupleIterator>>;
/// Creates elementwise iterator ranges for an iterator range of \c std::tuple.
///
/// \note Implementation for \c rosa::iterator::splitTupleIterator.
///
/// \tparam TupleIterator iterator of \c std::tuple
/// \tparam S0 indices for accessing elements of \c std::tuple
///
/// \param Begin the beginning of the iterator range to handle
/// \param End the end of the iterator range to handle
///
/// \note The last parameter provides indices as template parameter \p S0 and
/// its actual value is ignored.
///
/// \return \c std::tuple of elementwise iterator ranges corresponding to \p
/// Begin and \p End
template <typename TupleIterator, size_t... S0>
splitted_tuple_iterator_ranges_t<TupleIterator>
splitTupleIteratorImpl(TupleIterator &&Begin, const TupleIterator &End,
Seq<S0...>) noexcept {
using TB = TupleIteratorBuffer<TupleIterator>;
// Create a buffer in shared pointer. The buffer will be destructed once
// all corresponding element iterators (created below) have reached the end of
// the handled range or have been destructed.
auto Buffer = std::make_shared<TB>(std::move(Begin), End);
return {std::make_pair(element_iterator_t<TB, S0>(Buffer),
element_iterator_t<TB, S0>())...};
}
} // End namespace
+/// Gives the beginning of a range created by \c splitTupleIterator().
+///
+/// \see rosa::iterator::splitTupleIterator()
+///
+/// \note The signature of the template function uses implementation details.
+///
+/// \tparam TB buffer providing values to iterate
+/// \tparam I index of the values to iterator from \p TB
+///
+/// \param Range range to get the beginning of
+///
+/// \return beginning of \p Range
+template <typename TB, size_t I>
+element_iterator_t<TB, I> &begin(element_iterator_range_t<TB, I> &Range) {
+ return Range.first;
+}
+
+/// Gives the end of a range created by \c splitTupleIterator().
+///
+/// \see rosa::iterator::splitTupleIterator()
+///
+/// \note The signature of the template function uses implementation details.
+///
+/// \tparam TB buffer providing values to iterate
+/// \tparam I index of the values to iterator from \p TB
+///
+/// \param Range range to get the end of
+///
+/// \return end of \p Range
+template <typename TB, size_t I>
+element_iterator_t<TB, I> &end(element_iterator_range_t<TB, I> &Range) {
+ return Range.second;
+}
+
/// Creates elementwise iterator ranges for an iterator range of \c std::tuple.
///
/// \note The implementation utilizes \c splitTupleIteratorImpl.
///
/// Obtain element iterator ranges for an iterator range \c Begin and \c End of
/// iterator type \c TupleIterator of \c std::tuple<T1, T2, T3> as \code
/// auto [T1Range, T2Range, T3Range] = splitTupleIterator(std::move(Begin), End);
/// auto [T1Begin, T1End] = T1Range;
/// auto [T2Begin, T2End] = T2Range;
/// auto [T3Begin, T3End] = T3Range;
/// \endcode
+/// One range can also be dissected by dedicated functions like \code
+/// auto T1Begin = begin(T1Range);
+/// auto T1End = end(T1Range);
+/// \endcode
///
/// The function returns a tuple of ranges (i.e., \c std::pair of iterators),
/// which can be assigned to variables using structured binding. The ranges can
/// be dissected into begin and end iterators by separate structured bindings.
///
/// The function moves its first argument (i.e., \p Begin cannot be used
/// directly after splitting it). If the first argument is a variable, it needs
/// to be moved explicitly by \c std::move() as in the example.
///
/// \tparam TupleIterator iterator of \c std::tuple
///
/// \param Begin the beginning of the iterator range to handle
/// \param End the end of the iterator range to handle
///
/// \return \c std::tuple of elementwise iterator ranges corresponding to \p
/// Begin and \p End
template <typename TupleIterator>
splitted_tuple_iterator_ranges_t<TupleIterator>
splitTupleIterator(TupleIterator &&Begin, const TupleIterator &End) noexcept {
return splitTupleIteratorImpl(
std::move(Begin), End,
seq_t<std::tuple_size_v<typename TupleIterator::value_type>>());
}
} // End namespace iterator
} // End namespace rosa
#endif // ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jul 4, 2:18 AM (4 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157426
Default Alt Text
(29 KB)

Event Timeline