Program Listing for File competence_pack_union.hxx

Return to documentation for file (mesh_handle/internal/competence_pack_union.hxx)

/*
  This file is part of t8code.
  t8code is a C library to manage a collection (a forest) of multiple
  connected adaptive space-trees of general element classes in parallel.

  Copyright (C) 2026 the developers

  t8code is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  t8code is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with t8code; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#pragma once

#include <type_traits>

namespace t8_mesh_handle
{

template <template <typename> class... TCompetence>
struct element_competence_pack;

template <template <typename> class... TCompetence>
struct mesh_competence_pack;

namespace detail
{

// --- Unique insertion of one competence into a competence pack. ---
template <template <class> class TType>
struct tag
{
};

template <template <class> class TCompetence, template <class> class... TUnionCompetences>
inline constexpr bool contains_tag_v = std::disjunction_v<std::is_same<tag<TCompetence>, tag<TUnionCompetences>>...>;

template <template <template <typename> class...> class TPackType, template <class> class TCompetence,
          template <class> class... TUnionCompetences>
using insert_unique = std::conditional_t<contains_tag_v<TCompetence, TUnionCompetences...>,
                                         TPackType<TUnionCompetences...>, TPackType<TUnionCompetences..., TCompetence>>;

//--- Unique fold operation to fold competences into one competence pack without duplication. ---
template <template <template <typename> class...> class TPackType, typename TCompetencePack,
          template <class> class... TCompetences>
struct fold_unique;

template <template <template <typename> class...> class TPackType, template <class> class... TUnionCompetences>
struct fold_unique<TPackType, TPackType<TUnionCompetences...>>
{
  using type = TPackType<TUnionCompetences...>;
};

template <template <template <typename> class...> class TPackType, template <class> class... TUnionCompetences,
          template <class> class TCompetence, template <class> class... TOtherCompetences>
struct fold_unique<TPackType, TPackType<TUnionCompetences...>, TCompetence, TOtherCompetences...>
{
  using type = typename fold_unique<TPackType, insert_unique<TPackType, TCompetence, TUnionCompetences...>,
                                    TOtherCompetences...>::type;
};

//--- Unique union of two competence packs. ---
template <typename TPack1, typename TPack2>
struct union_two_competence_packs;

template <template <class> class... TCompetences1, template <class> class... TCompetences2>
struct union_two_competence_packs<element_competence_pack<TCompetences1...>, element_competence_pack<TCompetences2...>>
{
  using type =
    typename fold_unique<element_competence_pack, element_competence_pack<TCompetences1...>, TCompetences2...>::type;
};

template <template <class> class... TCompetences1, template <class> class... TCompetences2>
struct union_two_competence_packs<mesh_competence_pack<TCompetences1...>, mesh_competence_pack<TCompetences2...>>
{
  using type =
    typename fold_unique<mesh_competence_pack, mesh_competence_pack<TCompetences1...>, TCompetences2...>::type;
};

//--- Recursive union of multiple competence packs using the implementation for two packs. ---
template <typename TPack, typename... TPacks>
struct union_competence_packs
{
  using type = typename union_two_competence_packs<TPack, typename union_competence_packs<TPacks...>::type>::type;
};

template <typename TPack>
struct union_competence_packs<TPack>
{
  using type = TPack;
};

}  // namespace detail
}  // namespace t8_mesh_handle