#pragma once #include #include namespace AMDiS { struct FakeAssigner { template constexpr FakeAssigner& operator=(T&&) noexcept { return *this; } template constexpr FakeAssigner& operator+=(T&&) noexcept { return *this; } template constexpr FakeAssigner& operator-=(T&&) noexcept { return *this; } template constexpr FakeAssigner& operator*=(T&&) noexcept { return *this; } template constexpr FakeAssigner& operator/=(T&&) noexcept { return *this; } }; /// \brief A container-like data-structure not storing anything and with empty /// implementations in many container-interface functions. /** * This container that *does nothing* can be used as a dummy argument to * functions expecting a container, in order to omit specializations of * these functions for not providing a container. **/ template class FakeContainer : public FakeAssigner { public: using value_type = T; using size_type = std::size_t; struct const_iterator { using value_type = T; using reference = T; using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; constexpr T operator*() const noexcept { return value; } constexpr const_iterator& operator++() noexcept { return *this; } constexpr const_iterator operator++(int) noexcept { return *this; } /// Comparison of the iterator is always true constexpr bool operator==(const_iterator) const noexcept { return true; } constexpr bool operator!=(const_iterator) const noexcept { return false; } }; public: // constructor template constexpr explicit FakeContainer(Args&&...) noexcept {} template constexpr void init(S const&, bool) noexcept { /* do nothing */ } constexpr void finish() noexcept { /* do nothing */ } public: // modifiers and capacity template constexpr void scatter(Args&&...) noexcept { /* do nothing */ } template constexpr void push_back(Arg&&) noexcept { /* do nothing */ } template constexpr void emplace_back(Args&&...) noexcept { /* do nothing */ } template constexpr void reserve(Size&&) noexcept { /* do nothing */ } template constexpr void resize(Size&&) noexcept { /* do nothing */ } /// This container is never empty constexpr bool empty() const noexcept { return false; } public: // element access /// Mutable *element* access does return the container itself /// This allows to emulate nested containers template constexpr FakeContainer& operator[](Index&&) noexcept { return *this; } /// Const *element* access does return the container itself /// This allows to emulate nested containers template constexpr FakeContainer const& operator[](Index&&) const noexcept { return *this; } /// Mutable *element* access template constexpr FakeContainer& at(Index&&) noexcept { return *this; } /// Const *element* access template constexpr FakeContainer const& at(Index&&) const noexcept { return *this; } constexpr FakeContainer& front() noexcept { return *this; } constexpr FakeContainer const& front() const noexcept { return *this; } /// Container can be cast to the constant integral value constexpr operator T() const noexcept { return value; } public: // iterators /// Return iterator that always redirects to a bool true. constexpr const_iterator begin() const noexcept { return const_iterator{}; } /// Return iterator that always redirects to a bool true. constexpr const_iterator cbegin() const noexcept { return const_iterator{}; } public: // assignment operators /// Assignment operators from a fake assigner using FakeAssigner::operator=; using FakeAssigner::operator+=; using FakeAssigner::operator-=; using FakeAssigner::operator*=; using FakeAssigner::operator/=; }; } // end namespace AMDiS