mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-19 18:40:01 +02:00
144 lines
5.1 KiB
C++
144 lines
5.1 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-or-other
|
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
#pragma once
|
|
|
|
/**
|
|
* \file Result.h
|
|
* Result is a thin wrapper around std::vector and used for returning values
|
|
* from the detector. Since every module could have a different value, we need
|
|
* to return a vector instead of just a single value.
|
|
*
|
|
* Easy conversions to single values are provided using the squash method.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
#include "sls/ToString.h"
|
|
#include "sls/container_utils.h"
|
|
|
|
namespace sls {
|
|
|
|
/**
|
|
* @tparam T type to store in the result
|
|
* @tparam Allocator for the underlying vector, default
|
|
*/
|
|
template <class T, class Allocator = std::allocator<T>> class Result {
|
|
/** wrapped vector */
|
|
std::vector<T, Allocator> vec;
|
|
|
|
public:
|
|
Result() = default;
|
|
Result(std::initializer_list<T> list) : vec(list){};
|
|
|
|
/** Custom constructor from integer type to Result<ns> or Result<bool> */
|
|
template <typename V, typename = typename std::enable_if<
|
|
std::is_integral<V>::value &&
|
|
(std::is_same<T, time::ns>::value ||
|
|
std::is_same<T, bool>::value)>::type>
|
|
Result(const Result<V> &from) {
|
|
vec.reserve(from.size());
|
|
for (const auto &item : from)
|
|
vec.push_back(T(item));
|
|
}
|
|
|
|
/** Custom constructor from integer type to Result<ns> or Result<bool> */
|
|
template <typename V, typename = typename std::enable_if<
|
|
std::is_integral<V>::value &&
|
|
(std::is_same<T, time::ns>::value ||
|
|
std::is_same<T, bool>::value)>::type>
|
|
Result(Result<V> &from) {
|
|
vec.reserve(from.size());
|
|
for (const auto &item : from)
|
|
vec.push_back(T(item));
|
|
}
|
|
|
|
/** Custom constructor from integer type to Result<ns> or Result<bool> */
|
|
template <typename V, typename = typename std::enable_if<
|
|
std::is_integral<V>::value &&
|
|
(std::is_same<T, time::ns>::value ||
|
|
std::is_same<T, bool>::value)>::type>
|
|
Result(Result<V> &&from) {
|
|
vec.reserve(from.size());
|
|
for (const auto &item : from)
|
|
vec.push_back(T(item));
|
|
}
|
|
|
|
/**
|
|
* Forward arguments to the constructor of std::vector
|
|
* @tparam Args template paramter pack to forward
|
|
*/
|
|
template <typename... Args>
|
|
Result(Args &&...args) : vec(std::forward<Args>(args)...) {}
|
|
|
|
using value_type = typename std::vector<T>::value_type;
|
|
using iterator = typename std::vector<T>::iterator;
|
|
using const_iterator = typename std::vector<T>::const_iterator;
|
|
using size_type = typename std::vector<T>::size_type;
|
|
using reference = typename std::vector<T>::reference;
|
|
using const_reference = typename std::vector<T>::const_reference;
|
|
|
|
auto begin() noexcept -> decltype(vec.begin()) { return vec.begin(); }
|
|
auto begin() const noexcept -> decltype(vec.begin()) { return vec.begin(); }
|
|
auto cbegin() const noexcept -> decltype(vec.cbegin()) {
|
|
return vec.cbegin();
|
|
}
|
|
auto end() noexcept -> decltype(vec.end()) { return vec.end(); }
|
|
auto end() const noexcept -> decltype(vec.end()) { return vec.end(); }
|
|
auto cend() const noexcept -> decltype(vec.cend()) { return vec.cend(); }
|
|
auto size() const noexcept -> decltype(vec.size()) { return vec.size(); }
|
|
auto empty() const noexcept -> decltype(vec.empty()) { return vec.empty(); }
|
|
auto front() -> decltype(vec.front()) { return vec.front(); }
|
|
auto front() const -> decltype(vec.front()) { return vec.front(); }
|
|
void reserve(size_type new_cap) { vec.reserve(new_cap); }
|
|
|
|
template <typename V>
|
|
auto push_back(V value) -> decltype(vec.push_back(value)) {
|
|
vec.push_back(std::forward<V>(value));
|
|
}
|
|
|
|
auto operator[](size_type pos) -> decltype(vec[pos]) { return vec[pos]; }
|
|
const_reference operator[](size_type pos) const { return vec[pos]; }
|
|
|
|
/**
|
|
* If all elements are equal it returns the front value
|
|
* otherwise a default constructed T
|
|
*/
|
|
T squash() const { return Squash(vec); }
|
|
|
|
/**
|
|
* If all elements are equal it returns the front value
|
|
* otherwise throws an exception with custom message provided
|
|
*/
|
|
T tsquash(const std::string &error_msg) {
|
|
if (equal())
|
|
return vec.front();
|
|
else
|
|
throw RuntimeError(error_msg);
|
|
}
|
|
/**
|
|
* If all elements are equal return the front value, otherwise
|
|
* return the supplied default value
|
|
*/
|
|
T squash(const T &default_value) const {
|
|
return Squash(vec, default_value);
|
|
}
|
|
|
|
/** Test whether all elements of the result are equal */
|
|
bool equal() const noexcept { return allEqual(vec); }
|
|
|
|
/** Convert Result<T> to std::vector<T> */
|
|
operator std::vector<T>() { return vec; }
|
|
};
|
|
|
|
/**
|
|
* operator << overload to print Result, uses ToString for the conversion
|
|
* @tparam T type stored in the Result
|
|
*/
|
|
template <typename T>
|
|
std::ostream &operator<<(std::ostream &os, const Result<T> &res) {
|
|
return os << ToString(res);
|
|
}
|
|
|
|
} // namespace sls
|