Skip to content
Snippets Groups Projects
Select Git revision
  • 23654f4617012db9964406a0909e2dca90e467f2
  • master default protected
  • dev_mathis
  • develop
  • colored_track
  • show-text
  • dev_gian
  • efb-rendering
  • develop_marc
  • docstrings
  • pdocs
  • 0.4.0 protected
  • 0.3.6.1 protected
  • 0.3.6 protected
  • 0.3.5 protected
  • 0.3.4 protected
  • 0.3.3 protected
  • 0.3.2.3 protected
  • 0.3.2.2 protected
  • 0.3.2.1 protected
  • 0.3.2 protected
  • 0.3.1 protected
  • 0.3.0 protected
  • 0.2.16 protected
  • 0.2.15 protected
  • 0.2.14 protected
  • 0.2.13 protected
  • 0.2.12 protected
  • 0.2.11 protected
  • 0.2.10 protected
  • 0.2.9 protected
31 results

test_evaluate.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    variant.hh 12.55 KiB
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    #ifndef DUNE_COMMON_STD_VARIANT_HH
    #define DUNE_COMMON_STD_VARIANT_HH
    #include <tuple>
    #include <memory>
    #include <dune/common/hybridutilities.hh>
    #include <dune/common/exceptions.hh>
    
    namespace Dune {
    namespace Std {
    namespace Impl {
    
      // indicator value if something's not yet (or not any longer) valid
      constexpr const auto invalidIndex = std::numeric_limits<size_t>::max();
    
      /* helper constructs to find position of a type T in a pack Ts... */
      template <typename T, typename... Ts>
      struct index_in_pack;
    
      template <typename T, typename... Ts>
      struct index_in_pack<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
    
      template <typename T, typename U, typename... Ts>
      struct index_in_pack<T, U, Ts...> : std::integral_constant<std::size_t, 1 + index_in_pack<T, Ts...>::value> {};
    
      /* end helper constructs to find position of a type T in a pack Ts... */
    
      template<typename Tp>
      struct Buffer_ : std::aligned_storage<sizeof(Tp)> {
        using Storage = typename std::aligned_storage_t<sizeof(Tp)>::type;
        Storage storage_;
    
        void* addr() {
          return static_cast<void*>(&storage_);
        }
    
        const void* addr() const {
          return static_cast<const void*>(&storage_);
        }
    
        Tp* ptr() {
          return static_cast<Tp*>(addr());
        }
    
        const Tp* ptr() const {
          return static_cast<const Tp*>(addr());
        }
      };
    
      template<typename Tp, bool isTrivial>
      struct TypeStorage_ { };
    
      template<typename Tp>
      struct TypeStorage_<Tp, true> {
        TypeStorage_(Tp t) :
          tp_(t) {}
    
        template<typename... Args>
        TypeStorage_(Args... args) :
          tp_(args...) {}
    
        auto& get() {
          return tp_;
        }
        const auto& get() const {
          return tp_;
        }
    
        void reset() {};
    
        private:
        Tp tp_;
      };
    
      template<typename Tp>
      struct TypeStorage_<Tp, false> {
        TypeStorage_(Tp t) {
          ::new (&tp_) Tp(t);
        }
    
        template<typename... Args>
        TypeStorage_(Args... args) {
          ::new (&tp_) Tp(std::forward<Args>(args)...);
        }
    
        TypeStorage_() = delete;
    
        auto& get() {
          return *(tp_.ptr());
        }
        const auto& get() const {
          return *(tp_.ptr());
        }
    
        void reset() {
          // Properly destruct the member:
          tp_.ptr()->~Tp();
          // (the memory itself doesn't need to be free'd. This is done when the Buffer_ member gets destructed)
        }
    
        private:
        Buffer_<Tp> tp_;
      };
    
      template<typename... T>
      union variant_union_ {
        // dummy (this should never be called)
        void resetByIndex(size_t) {
          assert(false);
        };
      };
    
      template<typename Head_, typename... Tail_>
      union variant_union_<Head_, Tail_...> {
        constexpr variant_union_() :
          tail_() {}
    
        template<typename... Args>
        constexpr variant_union_(std::integral_constant<size_t, 0>, Args&&... args) :
          head_(std::forward<Args...>(args)...) {}
    
        template<size_t N, typename... Args>
        constexpr variant_union_(std::integral_constant<size_t, N>, Args&&... args) :
          tail_(std::integral_constant<size_t, N-1>(), std::forward<Args...>(args)...) {}
    
        auto& getByIndex(std::integral_constant<size_t, 0>) {
          return head_.get();
        }
    
        const auto& getByIndex(std::integral_constant<size_t, 0>) const {
          return head_.get();
        }
    
    
        template<size_t N>
        auto& getByIndex(std::integral_constant<size_t, N>) {
          return tail_.getByIndex(std::integral_constant<size_t, N-1>());
        }
    
        template<size_t N>
        const auto& getByIndex(std::integral_constant<size_t, N>) const {
          return tail_.getByIndex(std::integral_constant<size_t, N-1>());
        }
    
        void resetByIndex(size_t indexToReset) {
          if (indexToReset == 0) {
            head_.reset();
            return;
          }
          else {
            tail_.resetByIndex(indexToReset-1);
          }
        }
    
        template<typename Tp>
        void set(Tp&& obj) {
          using T = std::decay_t<Tp>;
          Dune::Hybrid::ifElse(std::is_same<T, Head_>(),
            [&](auto&& id)    { id(head_)=std::forward<Tp>(obj); },
            [&](auto&& id) { return id(tail_).set(std::forward<Tp>(obj)); }
          );
        }
    
        constexpr size_t size() const {
          return sizeof...(Tail_)+1;
        }
    
        private:
        TypeStorage_<Head_, std::is_trivial<Head_>::value> head_;
        variant_union_<Tail_...> tail_;
      };
    
      template<typename...T>
      struct variant_{
    
        constexpr variant_() :
          unions_(),
          index_(invalidIndex) {}
    
        template<typename Tp>
        constexpr variant_(Tp obj) :
          unions_(),
          index_(index_in_pack<Tp, T...>::value)
          {
            unions_.set(std::move(obj));
          }
    
        variant_(variant_&& other) {
          unions_ = std::move(other.unions_);
          index_ = other.index_;
          other.index_ = invalidIndex;
        }
    
        variant_(const variant_& other) {
          index_ = other.index_;
    
          namespace H = Dune::Hybrid;
          H::forEach(H::integralRange(std::integral_constant<size_t, size_>()), [&](auto i) {
                if(i==index_)
                  unions_.set(other.get<i>());
              });
        }
    
        variant_& operator=(const variant_& other) {
          if(index_ != invalidIndex)
            unions_.resetByIndex(index_);
    
          index_ = other.index_;
    
          namespace H = Dune::Hybrid;
          H::forEach(H::integralRange(std::integral_constant<size_t, size_>()), [&](auto i) {
                if(i==index_)
                  unions_.set(other.get<i>());
              });
          return *this;
        }
    
        variant_& operator=(variant_&& other) {
          unions_ = std::move(other.unions_);
          index_ = other.index_;
          other.index_ = invalidIndex;
    
          return *this;
        }
    
    
        template<typename Tp>
        auto& get() {
          constexpr size_t idx = index_in_pack<Tp, T...>::value;
          if (index_ != idx)
            DUNE_THROW(Dune::Exception, "Bad variant access.");
    
          return get<idx>();
        }
    
        template<typename Tp>
        const auto& get() const {
          constexpr size_t idx = index_in_pack<Tp, T...>::value;
          if (index_ != idx)
            DUNE_THROW(Dune::Exception, "Bad variant access.");
    
          return get<idx>();
        }
    
        template<typename Tp>
        Tp* get_if() {
          if (not holds_alternative<Tp>())
            return (Tp*) nullptr;
          else
            return &(get<Tp>());
        }
    
        template<typename Tp>
        const Tp* get_if() const {
          if (not holds_alternative<Tp>())
            return (Tp*) nullptr;
          else
            return &(get<Tp>());
        }
    
        template<size_t N>
        auto* get_if() {
          using Tp = std::decay_t<decltype(get<N>())>;
          if (not holds_alternative<N>())
            return (Tp*) nullptr;
          else
            return &(get<Tp>());
        }
    
        template<size_t N>
        const auto* get_if() const {
          using Tp = std::decay_t<decltype(get<N>())>;
          if (not holds_alternative<N>())
            return (Tp*) nullptr;
          else
            return &(get<Tp>());
        }
    
        template<size_t N>
        auto& get() {
          if (index_ != N || index_ == invalidIndex)
            DUNE_THROW(Dune::Exception, "Bad variant access.");
          return unions_.template getByIndex(std::integral_constant<size_t, N>());
        }
        template<size_t N>
        const auto& get() const {
          if (index_ != N || index_ == invalidIndex)
            DUNE_THROW(Dune::Exception, "Bad variant access.");
          return unions_.template getByIndex(std::integral_constant<size_t, N>());
        }
    
        template<typename Tp>
        constexpr Tp& operator=(Tp obj) {
          constexpr auto index = index_in_pack<Tp, T...>::value;
          // before setting a new object into the buffer, we have to destruct the old element
          if(not (index_ == index or index_ == invalidIndex)) {
            unions_.resetByIndex(index_);
          }
          unions_.set(std::move(obj));
          index_=index;
          return unions_.getByIndex(std::integral_constant<size_t,index>());
        }
    
        constexpr std::size_t index() const noexcept {
          return index_;
        }
    
        constexpr auto size() const {
          return sizeof...(T);
        }
    
        ~variant_() {
          if (index_ != invalidIndex) {
            unions_.resetByIndex(index_);
          }
        }
    
        /* \brief Apply visitor to the active variant.
         *
         * visit assumes that the result of
         * func(T) has the same type for all types T
         * in this variant.
         */
        template<typename F>
        auto visit(F&& func) {
          using namespace Dune::Hybrid;
    
          using Result = decltype(func(unions_.getByIndex(std::integral_constant<size_t, 0>())));
    
          return ifElse(std::is_same<Result, void>(), [&, this](auto id) {
              constexpr auto tsize = size_;
              Dune::Hybrid::forEach(Dune::Hybrid::integralRange(std::integral_constant<size_t, tsize>()), [&](auto i) {
                if (i==this->index_)
                  func(id(unions_).getByIndex(std::integral_constant<size_t, i>()));
                });
              return;},
            [&func,this](auto id) {
              constexpr auto tsize = size_;
    
              auto result = std::unique_ptr<Result>();
    
              Dune::Hybrid::forEach(Dune::Hybrid::integralRange(std::integral_constant<size_t, tsize>()), [&, this](auto i) {
                if (i==this->index_)
                  result = std::make_unique<Result>(func(id(this->unions_).getByIndex(std::integral_constant<size_t, i>())));
              });
          return *result;
           });
        }
    
        template<typename F>
        auto visit(F&& func) const {
          using namespace Dune::Hybrid;
    
          using Result = decltype(func(unions_.getByIndex(std::integral_constant<size_t, 0>())));
    
          return ifElse(std::is_same<Result, void>(), [&, this](auto id) {
              constexpr auto tsize = size_;
              Dune::Hybrid::forEach(Dune::Hybrid::integralRange(std::integral_constant<size_t, tsize>()), [&](auto i) {
                if (i==this->index_)
                  func(id(unions_).getByIndex(std::integral_constant<size_t, i>()));
                });
              return;},
            [&func,this](auto id) {
              constexpr auto tsize = size_;
    
              auto result = std::unique_ptr<Result>();
    
              Dune::Hybrid::forEach(Dune::Hybrid::integralRange(std::integral_constant<size_t, tsize>()), [&, this](auto i) {
                if (i==this->index_)
                  result = std::make_unique<Result>(func(id(this->unions_).getByIndex(std::integral_constant<size_t, i>())));
              });
          return *result;
           });
        }
    
        /** \brief Check if a given type is the one that is currently active in the variant. */
        template<typename Tp>
        constexpr bool holds_alternative() const {
          // I have no idea how this could be really constexpr, but for STL-conformity,
          // I'll leave the modifier there.
          return (index_in_pack<Tp, T...>::value == index_);
        }
    
        /** \brief Check if a given type is the one that is currently active in the variant. */
        template<size_t N>
        constexpr bool holds_alternative() const {
          // I have no idea how this could be really constexpr, but for STL-conformity,
          // I'll leave the modifier there.
          return (N == index_);
        }
    
        private:
        variant_union_<T...> unions_;
        std::size_t index_;
        constexpr static auto size_ = sizeof...(T);
      };
    
    } // end namespace Impl
    
      /** \brief Incomplete re-implementation of C++17's std::variant. */
      template<typename ...T>
      using variant = Impl::variant_<T...>;
    
      template<size_t N, typename... T>
      auto& get(variant<T...>& var) {
        return var.template get<N>();
      }
    
      template<size_t N, typename... T>
      const auto& get(const variant<T...>& var) {
        return var.template get<N>();
      }
    
      template<typename F, typename... T>
      auto visit(F&& visitor, variant<T...>& var) {
        return var.visit(std::forward<F>(visitor));
      }
    
      template<typename F, typename... T>
      auto visit(F&& visitor, const variant<T...>& var) {
        return var.visit(std::forward<F>(visitor));
      }
    
      template<typename Tp, typename ...T>
      auto& get(variant<T...>& var) {
        return var.template get<Tp>();
      }
    
      template<typename Tp, typename ...T>
      const auto& get(const variant<T...>& var) {
        return var.template get<Tp>();
      }
    
      template<typename Tp, typename ...T>
      const auto* get_if(const variant<T...>& var) {
        return var.template get_if<Tp>();
      }
    
      template<typename Tp, typename ...T>
      auto* get_if(variant<T...>& var) {
        return var.template get_if<Tp>();
      }
    
      template<size_t N, typename ...T>
      const auto* get_if(const variant<T...>& var) {
        return var.template get_if<N>();
      }
    
      template<size_t N, typename ...T>
      auto* get_if(variant<T...>& var) {
        return var.template get_if<N>();
      }
    
      template<typename Tp, typename ...T>
      constexpr bool holds_alternative(const variant<T...>& var) {
        return var.template holds_alternative<Tp>();
      }
    
      template <typename... T>
      constexpr auto variant_size_v(const variant<T...>&) {
        return std::integral_constant<std::size_t,sizeof...(T)>::value;
      }
    
    } // end namespace Std
    } // end namespace Dune
    #endif