#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 #include #include #include "ToString.h" #include "container_utils.h" namespace sls { /** * @tparam T type to store in the result * @tparam Allocator for the underlying vector, default */ template > class Result { /** wrapped vector */ std::vector vec; public: Result() = default; Result(std::initializer_list list) : vec(list){}; /** Custom constructor from integer type to Result or Result */ template ::value && (std::is_same::value || std::is_same::value)>::type> Result(const Result &from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); } /** Custom constructor from integer type to Result or Result */ template ::value && (std::is_same::value || std::is_same::value)>::type> Result(Result &from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); } /** Custom constructor from integer type to Result or Result */ template ::value && (std::is_same::value || std::is_same::value)>::type> Result(Result &&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 Result(Args &&... args) : vec(std::forward(args)...) {} using value_type = typename std::vector::value_type; using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; using size_type = typename std::vector::size_type; using reference = typename std::vector::reference; using const_reference = typename std::vector::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 auto push_back(V value) -> decltype(vec.push_back(value)) { vec.push_back(std::forward(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 to std::vector */ operator std::vector() { return vec; } }; /** * operator << overload to print Result, uses ToString for the conversion * @tparam T type stored in the Result */ template std::ostream &operator<<(std::ostream &os, const Result &res) { return os << ToString(res); } } // namespace sls