Skip to content

Commit

Permalink
Merge pull request #452 from mtao/mtao/filtering_unique_remove_tuples
Browse files Browse the repository at this point in the history
Mtao/filtering unique remove types from variadic packs
  • Loading branch information
mtao authored Oct 16, 2023
2 parents 3a9ff3f + 5ac1610 commit 9385b55
Show file tree
Hide file tree
Showing 10 changed files with 342 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/wmtk/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ set(SRC_FILES
TupleInspector.hpp
)
target_sources(wildmeshing_toolkit PRIVATE ${SRC_FILES})


add_subdirectory(metaprogramming)
12 changes: 12 additions & 0 deletions src/wmtk/utils/metaprogramming/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(SRC_FILES
DerivedReferenceWrapperVariantTraits.hpp
ReferenceWrappedFunctorReturnCache.hpp
ReferenceWrappedFunctorReturnType.hpp
ReferenceWrapperVariant.hpp
as_variant.hpp
unwrap_ref.hpp
)

target_sources(wildmeshing_toolkit PRIVATE ${SRC_FILES})

add_subdirectory(tuple)
7 changes: 7 additions & 0 deletions src/wmtk/utils/metaprogramming/tuple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
set(SRC_FILES
concatenate_types.hpp
get_unique_remove_void_types.hpp
get_unique_types.hpp
remove_void_types.hpp
)
target_sources(wildmeshing_toolkit PRIVATE ${SRC_FILES})
27 changes: 27 additions & 0 deletions src/wmtk/utils/metaprogramming/tuple/concatenate_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include <tuple>

namespace wmtk::utils::metaprogramming::tuple {


// creates a tuple that concatenates the types passed in


// generic case so we can specialize with tuples passed in
template <typename T, typename U>
struct concatenate_types
{
};

// main case where we pass in two tuples
template <typename... Ts, typename... Us>
struct concatenate_types<std::tuple<Ts...>, std::tuple<Us...>>
{
using type = std::tuple<Ts..., Us...>;
};


// alias to underlying type
template <typename T, typename U>
using concatenate_types_t = typename concatenate_types<T, U>::type;
} // namespace wmtk::utils::metaprogramming::tuple
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once
#include <tuple>
#include <type_traits>
#include "get_unique_types.hpp"
#include "remove_void_types.hpp"


namespace wmtk::utils::metaprogramming::tuple {


// given a set of types, a tuple without the voids and makes unique types
template <typename... Ts>
using get_unique_remove_void_types_t = // get_unique_t<Ts...>;
typename detail::remove_void_tuple<void, get_unique_types_t<Ts...>>::type;
}

74 changes: 74 additions & 0 deletions src/wmtk/utils/metaprogramming/tuple/get_unique_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once
#include <tuple>
#include <type_traits>
#include "concatenate_types.hpp"

namespace wmtk::utils::metaprogramming::tuple {


// given a tuple, extracts a tuple with only unique types in the input

// strategy is to recursively extract the last copy of any given type


// alternates between get_unique_types<tuple<Ts...> with
// main_unique_tuple_types<T,std::tuple<Ts...>> to combine Ts... and T,Ts... as necessary

namespace detail {


// basic initializations - by default return empty in case the input is empty (which is not caught
// by later cases)
template <typename...>
struct get_unique_types
{
using type = std::tuple<>;
};
// basic initialization, expects a T and a Tuple
template <typename T, typename RemainingTuple>
struct get_unique_types_tuple
{
};
// convenience to avoid typename for get_unique_types...
template <typename... Ts>
using get_unique_types_t = typename get_unique_types<Ts...>::type;


// actual base case - single type is unique so we return that type
template <typename T>
struct get_unique_types<T>
{
using type = std::tuple<T>;
};


// from a list of types, check if the first is unique compared to the rest
template <typename T, typename... Ts>
struct get_unique_types<T, Ts...>
{
using type = typename get_unique_types_tuple<T, std::tuple<Ts...>>::type;
};


// do the meat of the implementation - check if T is unique in T,Ts...
// if so then add it to the unique of the rest
template <typename T, typename... Ts>
struct get_unique_types_tuple<T, std::tuple<Ts...>>
{
// is t unique among T,Ts...
constexpr static bool t_is_unique = (!std::is_same_v<T, Ts> && ...);
// if its unique then create {T} otherwise {}
using adding_t_type = std::conditional_t<t_is_unique, std::tuple<T>, std::tuple<>>;

// concatenate adding_t_type \cup unique(Ts...)
using type = concatenate_types_t<adding_t_type, get_unique_types_t<Ts...>>;
};


} // namespace detail

// main access point
template <typename... Ts>
using get_unique_types_t = detail::get_unique_types_t<Ts...>;

} // namespace wmtk::utils::metaprogramming::tuple
49 changes: 49 additions & 0 deletions src/wmtk/utils/metaprogramming/tuple/remove_void_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once
#include <tuple>
#include "concatenate_types.hpp"


namespace wmtk::utils::metaprogramming::tuple {
namespace detail {
template <typename...>
struct remove_void
{
using type = std::tuple<>;
};
template <>
struct remove_void<void>
{
using type = std::tuple<>;
};
template <typename T>
struct remove_void<T>
{
using type = std::tuple<T>;
};

template <typename... Ts>
using remove_void_t = typename remove_void<Ts...>::type;

template <typename T, typename RemainingTuple>
struct remove_void_tuple
{
};
template <typename T, typename... Ts>
struct remove_void_tuple<T, std::tuple<Ts...>>
{
constexpr static bool t_not_void = !std::is_same_v<T, void>;
using adding_t_type = std::conditional_t<t_not_void, std::tuple<T>, std::tuple<>>;

using type = concatenate_types_t<adding_t_type, remove_void_t<Ts...>>;
};

template <typename T, typename... Ts>
struct remove_void<T, Ts...>
{
using type = typename remove_void_tuple<T, std::tuple<Ts...>>::type;
};
} // namespace detail

template <typename... Ts>
using remove_void_types_t = detail::remove_void_t<Ts...>;
} // namespace wmtk::utils::metaprogramming::tuple
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(TEST_SOURCES
test_3d_operations.cpp
test_multi_mesh.cpp
test_variant_metaprogramming.cpp
test_tuple_metaprogramming.cpp


tools/DEBUG_PointMesh.hpp
Expand Down
151 changes: 151 additions & 0 deletions tests/test_tuple_metaprogramming.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include <spdlog/spdlog.h>
#include <catch2/catch_test_macros.hpp>
#include <wmtk/utils/metaprogramming/tuple/get_unique_remove_void_types.hpp>
#include <wmtk/utils/metaprogramming/tuple/get_unique_types.hpp>
#include <wmtk/utils/metaprogramming/tuple/remove_void_types.hpp>
#include <wmtk/utils/metaprogramming/tuple/concatenate_types.hpp>

TEST_CASE("test_concatenate_metaprogramming", "[tuple]")
{

{
using a = std::tuple<>;
using b = std::tuple<>;
using c = wmtk::utils::metaprogramming::tuple::concatenate_types_t<a,b>;
static_assert(std::is_same_v<c,std::tuple<>>);
}
{
using a = std::tuple<>;
using b = std::tuple<int,long,float>;
using c = wmtk::utils::metaprogramming::tuple::concatenate_types_t<a,b>;
static_assert(std::is_same_v<c,std::tuple<int,long,float>>);
}
{
using a = std::tuple<int,long,float>;
using b = std::tuple<>;
using c = wmtk::utils::metaprogramming::tuple::concatenate_types_t<a,b>;
static_assert(std::is_same_v<c,std::tuple<int,long,float>>);
}
{
using a = std::tuple<int,long,float>;
using b = std::tuple<uint32_t,int>;
using c = wmtk::utils::metaprogramming::tuple::concatenate_types_t<a,b>;
static_assert(std::is_same_v<c,std::tuple<int,long,float,uint32_t,int>>);
}

}
TEST_CASE("test_remove_void_metaprogramming", "[tuple]")
{

{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<>;
static_assert(std::is_same_v<type,std::tuple<>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<int,long,float>;
static_assert(std::is_same_v<type,std::tuple<int,long,float>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<void>;
static_assert(std::is_same_v<type,std::tuple<>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<void,int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<int,void>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<int,void,long>;
static_assert(std::is_same_v<type,std::tuple<int,long>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::remove_void_types_t<void,int,void,long>;
static_assert(std::is_same_v<type,std::tuple<int,long>>);
}

}
TEST_CASE("test_get_unique_metaprogramming", "[tuple]")
{

{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<>;
static_assert(std::is_same_v<type,std::tuple<>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<int,int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<int,int,int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<int,long,int>;
static_assert(std::is_same_v<type,std::tuple<long,int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<int,long,long>;
static_assert(std::is_same_v<type,std::tuple<int,long>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_types_t<long,float,int,long,long,long,int>;
static_assert(std::is_same_v<type,std::tuple<float,long,int>>);
}

}
TEST_CASE("test_get_unique_remove_void_types_metaprogramming", "[tuple]")
{

{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<>;
static_assert(std::is_same_v<type,std::tuple<>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<void>;
static_assert(std::is_same_v<type,std::tuple<>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<int,int,void>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<int,void,int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<void,int,int>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<void,int,void,int,void>;
static_assert(std::is_same_v<type,std::tuple<int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<int,long,void,int>;
static_assert(std::is_same_v<type,std::tuple<long,int>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<int,void,long,long>;
static_assert(std::is_same_v<type,std::tuple<int,long>>);
}
{
using type = wmtk::utils::metaprogramming::tuple::get_unique_remove_void_types_t<void,long,void,float,int,long,void,long,long,int,void,void,void>;
static_assert(std::is_same_v<type,std::tuple<float,long,int>>);
}

}
4 changes: 2 additions & 2 deletions tests/test_variant_metaprogramming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ size_t TestRefType::get_index(const Input& input)
} // namespace wmtk::utils::metaprogramming


TEST_CASE("test_variant_multiprogramming", "[metaprogramming]")
TEST_CASE("test_variant_metaprogramming", "[metaprogramming]")
{
static_assert(std::is_same_v<TestRefType::BaseType, Input>);
static_assert(std::is_same_v<TestRefType::DerivedTypesTuple, std::tuple<A, B, C>>);
Expand Down Expand Up @@ -135,7 +135,7 @@ TEST_CASE("test_variant_multiprogramming", "[metaprogramming]")
c_ref);
}

TEST_CASE("test_variant_multiprogramming_cache", "[metaprogramming]")
TEST_CASE("test_variant_metaprogramming_cache", "[metaprogramming]")
{
A a(0);
B b(2);
Expand Down

0 comments on commit 9385b55

Please sign in to comment.