Skip to content

Commit

Permalink
11;rgb:1818/1818/1818# This is the 1st commit message:
Browse files Browse the repository at this point in the history
implement alpaka::meta::isList and alpaka::meta::toList

- `alpaka::meta::isList` checks a given type is a type list
- `alpaka::meta::toList` checks if a given type is a type list and if not, create a type list with all given types
  • Loading branch information
SimeonEhrig committed May 15, 2024
1 parent f3664a1 commit 71a5f80
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
59 changes: 59 additions & 0 deletions include/alpaka/meta/TypeListOps.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <tuple>
#include <type_traits>

namespace alpaka::meta
Expand Down Expand Up @@ -35,4 +36,62 @@ namespace alpaka::meta
{
static constexpr bool value = std::is_same_v<Head, Value> || Contains<List<Tail...>, Value>::value;
};

// copied from https://stackoverflow.com/a/51073558/22035743
template<typename T>
struct IsList : std::false_type
{
};

template<template<typename...> class TList, typename... TTypes>
struct IsList<TList<TTypes...>> : 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<typename T>
constexpr bool isList = IsList<std::decay_t<T>>::value;

namespace detail
{
template<template<typename...> class TListType, typename TType, typename = void>
struct ToListImpl
{
using type = TListType<TType>;
};

template<template<typename...> class TListType, typename TList>
struct ToListImpl<TListType, TList, std::enable_if_t<alpaka::meta::isList<TList>>>
{
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<template<typename...> class TListType, typename... T>
struct ToList;

template<template<typename...> class TListType, typename T>
struct ToList<TListType, T> : detail::ToListImpl<TListType, T>
{
};

template<template<typename...> class TListType, typename T, typename... Ts>
struct ToList<TListType, T, Ts...>
{
using type = TListType<T, Ts...>;
};

//! \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<typename... T>
using toTuple = typename ToList<std::tuple, T...>::type;


} // namespace alpaka::meta
41 changes: 41 additions & 0 deletions test/unit/meta/src/TypeListOpsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include <tuple>
#include <type_traits>

template<typename... TTypes>
struct TypeList
{
};

TEST_CASE("front", "[meta]")
{
STATIC_REQUIRE(std::is_same_v<alpaka::meta::Front<std::tuple<int>>, int>);
Expand All @@ -26,3 +31,39 @@ TEST_CASE("contains", "[meta]")
STATIC_REQUIRE(alpaka::meta::Contains<std::tuple<short, int, double, float>, float>::value);
STATIC_REQUIRE(!alpaka::meta::Contains<std::tuple<short, int, double, float>, char>::value);
}

TEST_CASE("isList", "[meta]")
{
STATIC_REQUIRE(alpaka::meta::isList<std::tuple<int>>);
STATIC_REQUIRE(alpaka::meta::isList<std::tuple<int, float>>);
STATIC_REQUIRE_FALSE(alpaka::meta::isList<int>);

STATIC_REQUIRE(alpaka::meta::isList<TypeList<int>>);
STATIC_REQUIRE(alpaka::meta::isList<TypeList<int, float, double>>);
}

TEST_CASE("ToList", "[meta]")
{
STATIC_REQUIRE(std::is_same_v<typename alpaka::meta::ToList<TypeList, int>::type, TypeList<int>>);
STATIC_REQUIRE(std::is_same_v<
typename alpaka::meta::ToList<TypeList, float, double, int>::type,
TypeList<float, double, int>>);
STATIC_REQUIRE(
std::is_same_v<typename alpaka::meta::ToList<TypeList, TypeList<unsigned int>>::type, TypeList<unsigned int>>);
STATIC_REQUIRE(std::is_same_v<
typename alpaka::meta::ToList<TypeList, TypeList<float, double, int>>::type,
TypeList<float, double, int>>);

STATIC_REQUIRE(std::is_same_v<typename alpaka::meta::ToList<std::tuple, int>::type, std::tuple<int>>);
STATIC_REQUIRE(
std::is_same_v<typename alpaka::meta::ToList<std::tuple, std::tuple<float>>::type, std::tuple<float>>);
}

TEST_CASE("toTuple", "[meta]")
{
STATIC_REQUIRE(std::is_same_v<alpaka::meta::toTuple<int>, std::tuple<int>>);
STATIC_REQUIRE(std::is_same_v<alpaka::meta::toTuple<int, float, double>, std::tuple<int, float, double>>);
STATIC_REQUIRE(std::is_same_v<alpaka::meta::toTuple<std::tuple<int>>, std::tuple<int>>);
STATIC_REQUIRE(
std::is_same_v<alpaka::meta::toTuple<std::tuple<int, float, double>>, std::tuple<int, float, double>>);
}

0 comments on commit 71a5f80

Please sign in to comment.