#ifndef CONTAINER_UTILS_H #define CONTAINER_UTILS_H #include <algorithm> #include <memory> #include <numeric> #include <sstream> #include <string> #include <type_traits> #include <vector> #include "TypeTraits.h" namespace sls { // C++11 make_unique implementation for exception safety // already available as std::make_unique in C++14 template <typename T, typename... Args> typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(Args &&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } template <typename T> typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(std::size_t n) { typedef typename std::remove_extent<T>::type RT; return std::unique_ptr<T>(new RT[n]); } /** Compare elements in a Container to see if they are all equal */ template <typename Container> bool allEqual(const Container &c) { if (!c.empty() && std::all_of(begin(c), end(c), [c](const typename Container::value_type &element) { return element == c.front(); })) return true; return false; } /** * Compare elements but with specified tolerance, useful * for floating point values. */ template <typename T> typename std::enable_if<std::is_arithmetic<T>::value, bool>::type allEqualWithTol(const std::vector<T> &container, const T tol) { if (container.empty()) return false; const auto &first = container[0]; return std::all_of(container.cbegin(), container.cend(), [first, tol](const T &element) { return (std::abs(element - first) < tol); }); } template <typename T> bool allEqualTo(const std::vector<T> &container, const T value) { if (container.empty()) return false; return std::all_of(container.cbegin(), container.cend(), [value](const T &element) { return element == value; }); } template <typename T> bool allEqualToWithTol(const std::vector<T> &container, const T value, const T tol) { if (container.empty()) return false; return std::all_of(container.cbegin(), container.cend(), [value, tol](const T &element) { return (std::abs(element - value) < tol); }); } template <typename T> bool anyEqualTo(const std::vector<T> &container, const T value) { return std::any_of(container.cbegin(), container.cend(), [value](const T &element) { return element == value; }); } template <typename T> bool anyEqualToWithTol(const std::vector<T> &container, const T value, const T tol) { return std::any_of(container.cbegin(), container.cend(), [value, tol](const T &element) { return (std::abs(element - value) < tol); }); } template <typename T> typename std::enable_if<std::is_arithmetic<T>::value, T>::type sum(const std::vector<T> &container) { return std::accumulate(container.cbegin(), container.cend(), T{0}); } template <typename T> T minusOneIfDifferent(const std::vector<T> &container) { if (allEqual(container)) return container.front(); return static_cast<T>(-1); } inline int minusOneIfDifferent(const std::vector<bool> &container) { if (allEqual(container)) return static_cast<int>(container.front()); return -1; } template <typename T> std::vector<T> minusOneIfDifferent(const std::vector<std::vector<T>> &container) { if (allEqual(container)) return container.front(); return std::vector<T>{-1}; } template <typename T, size_t size> std::array<T, size> minusOneIfDifferent(const std::vector<std::array<T, size>> &container) { if (allEqual(container)) return container.front(); std::array<T, size> arr; arr.fill(static_cast<T>(-1)); return arr; } /** * Return the first value if all values are equal * otherwise return default_value. If no default * value is supplied it will be default constructed */ template <typename Container> typename Container::value_type Squash(const Container &c, typename Container::value_type default_value = {}) { if (!c.empty() && std::all_of(begin(c), end(c), [c](const typename Container::value_type &element) { return element == c.front(); })) return c.front(); return default_value; } } // namespace sls #endif // CONTAINER_UTILS_H