diff --git a/source/cppassist/CMakeLists.txt b/source/cppassist/CMakeLists.txt index 3335c54..f6bcd40 100644 --- a/source/cppassist/CMakeLists.txt +++ b/source/cppassist/CMakeLists.txt @@ -96,6 +96,9 @@ set(headers ${include_path}/threading/parallelfor.h ${include_path}/threading/parallelfor.inl + + ${include_path}/typelist/TypeList.h + ${include_path}/typelist/TypeList.inl ${include_path}/cmdline/ArgumentParser.h ${include_path}/cmdline/ArgumentParser.inl diff --git a/source/cppassist/include/cppassist/typelist/TypeList.h b/source/cppassist/include/cppassist/typelist/TypeList.h new file mode 100644 index 0000000..e6ed829 --- /dev/null +++ b/source/cppassist/include/cppassist/typelist/TypeList.h @@ -0,0 +1,68 @@ + +#pragma once + + +namespace cppassist +{ + + +/** +* @brief +* A compile-time list of types. +* +* This is the default template for template specializations. +*/ +template +class TypeList; + +/** +* @brief +* A compile-time list of types. +* +* This is the template specialization for non-zero type lists. +* There is an interface to call a template operator() on a Functor for each type in the type list. +*/ +template +class TypeList +{ +public: + /** + * @brief + * Call the template operator() on the Functor for each type. + * + * @param[in] callback + * The functor, supporting a templated operator() + */ + template + static void apply(Functor && callback); +}; + +/** +* @brief +* A compile-time list of types. +* +* This is the template specialization for a zero type list. +* It is used as the recursion break condition. +*/ +template <> +class TypeList<> +{ +public: + /** + * @brief + * Call the template operator() on the Functor for each type. + * + * As this is the empty type list, no operator is called. + * + * @param[in] callback + * The functor, supporting a templated operator() + */ + template + static void apply(Functor && callback); +}; + + +} // namespace cppassist + + +#include diff --git a/source/cppassist/include/cppassist/typelist/TypeList.inl b/source/cppassist/include/cppassist/typelist/TypeList.inl new file mode 100644 index 0000000..de0e8ce --- /dev/null +++ b/source/cppassist/include/cppassist/typelist/TypeList.inl @@ -0,0 +1,27 @@ + +#pragma once + + +#include + + +namespace cppassist +{ + + +template +template +void TypeList::apply(Functor && callback) +{ + (callback.template operator())(); + + TypeList::apply(std::forward(callback)); +} + +template +void TypeList<>::apply(Functor && /*callback*/) +{ +} + + +} // namespace cppassist diff --git a/source/tests/cppassist-test/CMakeLists.txt b/source/tests/cppassist-test/CMakeLists.txt index 2519a5e..a2e1433 100644 --- a/source/tests/cppassist-test/CMakeLists.txt +++ b/source/tests/cppassist-test/CMakeLists.txt @@ -35,6 +35,9 @@ set(sources # flags flags_test.cpp + + # typelist + typelist_test.cpp # memory make_unique_test.cpp diff --git a/source/tests/cppassist-test/typelist_test.cpp b/source/tests/cppassist-test/typelist_test.cpp new file mode 100644 index 0000000..807a1f1 --- /dev/null +++ b/source/tests/cppassist-test/typelist_test.cpp @@ -0,0 +1,51 @@ + +#include + +#include + + +class typelist_test : public testing::Test +{ +public: + typelist_test() + : intCallcount(0) + , floatCallcount(0) + , boolCallcount(0) + { + } + + template + void operator()() + { + if (typeid(T) == typeid(int)) + { + ++intCallcount; + } + + if (typeid(T) == typeid(float)) + { + ++floatCallcount; + } + + if (typeid(T) == typeid(bool)) + { + ++boolCallcount; + } + } +protected: + int intCallcount; + int floatCallcount; + int boolCallcount; +}; + + +TEST_F(typelist_test, ListApply) +{ + using list = cppassist::TypeList; + + list::apply(*this); + + ASSERT_EQ(intCallcount, 1); + ASSERT_EQ(floatCallcount, 1); + ASSERT_EQ(boolCallcount, 1); +}