diff --git a/include/alpaka/meta/TypeListOps.hpp b/include/alpaka/meta/TypeListOps.hpp index 2d6bcfe7f45f..0a21fe3c4019 100644 --- a/include/alpaka/meta/TypeListOps.hpp +++ b/include/alpaka/meta/TypeListOps.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include namespace alpaka::meta @@ -35,4 +36,62 @@ namespace alpaka::meta { static constexpr bool value = std::is_same_v || Contains, Value>::value; }; + + // copied from https://stackoverflow.com/a/51073558/22035743 + template + struct IsList : std::false_type + { + }; + + template class TList, typename... TTypes> + struct IsList> : std::true_type + { + }; + + //! \brief Checks whether the specified type is a list. List is a type with a variadic number of template types. + //! \tparam T possible list + template + constexpr bool isList = IsList>::value; + + namespace detail + { + template class TListType, typename TType, typename = void> + struct ToListImpl + { + using type = TListType; + }; + + template class TListType, typename TList> + struct ToListImpl>> + { + using type = TList; + }; + } // namespace detail + + //! \brief Takes an arbitrary number of types (T) and creates a type list of type TListType with the types (T). If + //! T is a single template parameter and it satisfies alpaka::meta::isList, the type of the structure is T (no type + //! change). + //! \tparam TListType type of the created list + //! \tparam T possible list types or type list + template class TListType, typename... T> + struct ToList; + + template class TListType, typename T> + struct ToList : detail::ToListImpl + { + }; + + template class TListType, typename T, typename... Ts> + struct ToList + { + using type = TListType; + }; + + //! \brief If T is a single argument and a type list (fullfil alpaka::meta::isList), the return type is T. + //! Otherwise, std::tuple is returned with T types as template parameters. + //! \tparam T possible list types or type list + template + using toTuple = typename ToList::type; + + } // namespace alpaka::meta diff --git a/test/unit/meta/src/TypeListOpsTest.cpp b/test/unit/meta/src/TypeListOpsTest.cpp index b15e77733cc2..8661420c810f 100644 --- a/test/unit/meta/src/TypeListOpsTest.cpp +++ b/test/unit/meta/src/TypeListOpsTest.cpp @@ -9,6 +9,11 @@ #include #include +template +struct TypeList +{ +}; + TEST_CASE("front", "[meta]") { STATIC_REQUIRE(std::is_same_v>, int>); @@ -26,3 +31,39 @@ TEST_CASE("contains", "[meta]") STATIC_REQUIRE(alpaka::meta::Contains, float>::value); STATIC_REQUIRE(!alpaka::meta::Contains, char>::value); } + +TEST_CASE("isList", "[meta]") +{ + STATIC_REQUIRE(alpaka::meta::isList>); + STATIC_REQUIRE(alpaka::meta::isList>); + STATIC_REQUIRE_FALSE(alpaka::meta::isList); + + STATIC_REQUIRE(alpaka::meta::isList>); + STATIC_REQUIRE(alpaka::meta::isList>); +} + +TEST_CASE("ToList", "[meta]") +{ + STATIC_REQUIRE(std::is_same_v::type, TypeList>); + STATIC_REQUIRE(std::is_same_v< + typename alpaka::meta::ToList::type, + TypeList>); + STATIC_REQUIRE( + std::is_same_v>::type, TypeList>); + STATIC_REQUIRE(std::is_same_v< + typename alpaka::meta::ToList>::type, + TypeList>); + + STATIC_REQUIRE(std::is_same_v::type, std::tuple>); + STATIC_REQUIRE( + std::is_same_v>::type, std::tuple>); +} + +TEST_CASE("toTuple", "[meta]") +{ + STATIC_REQUIRE(std::is_same_v, std::tuple>); + STATIC_REQUIRE(std::is_same_v, std::tuple>); + STATIC_REQUIRE(std::is_same_v>, std::tuple>); + STATIC_REQUIRE( + std::is_same_v>, std::tuple>); +}