Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMartin Hořeňovský2026-08-20 21:38:48 +0200
committerMartin Hořeňovský2026-08-23 11:31:50 +0200
commit9a2b2ee8d6d325fc0d9ccf449fb375e78c6f3480 (patch)
treeeb9c99dc3999d24438d5d48b0c80cdbd9f4fdebc
parentef3a728265292e6a1dbec727b0099d3d8b3f6420 (diff)
downloadcatch3-9a2b2ee8d6d325fc0d9ccf449fb375e78c6f3480.tar.gz
Avoid stamping out common type helpers in each templated test cases
This provides small (but measurable) improvements in compilation times when a TU has multiple test cases templated over the same types.
-rw-r--r--src/catch2/internal/catch_preprocessor.hpp74
1 files changed, 45 insertions, 29 deletions
diff --git a/src/catch2/internal/catch_preprocessor.hpp b/src/catch2/internal/catch_preprocessor.hpp
index fae95e9d..c112905d 100644
--- a/src/catch2/internal/catch_preprocessor.hpp
+++ b/src/catch2/internal/catch_preprocessor.hpp
@@ -9,6 +9,7 @@
#define CATCH_PREPROCESSOR_HPP_INCLUDED
#include <catch2/internal/catch_preprocessor_remove_parens.hpp>
+#include <catch2/internal/catch_meta.hpp>
#if defined(__GNUC__)
// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
@@ -22,6 +23,34 @@ namespace Catch {
struct priority_tag : priority_tag<N - 1> {};
template <>
struct priority_tag<0> {};
+
+ // This is a bunch of helpers for the templated test case handling.
+ // They should live elsewhere in the long run, but as an in-between
+ // step we toss them all here.
+ template <typename...> struct TypeList {};
+ template <typename... Ts>
+ constexpr auto get_wrapper( priority_tag<1> ) noexcept -> TypeList<Ts...> { return {}; }
+ template <template <typename...> class...> struct TemplateTypeList {};
+ // Clang 20 and 21 cannot handle an explicitly specified all-pack
+ // template-template parameter here ("conflicting deduction" regression,
+ // llvm/llvm-project#130778; fixed for Clang 22).
+ // Remove get_template_wrapper once Clang 21 is no longer supported.
+ template <template <typename...> class C, template <typename...> class... Cs>
+ constexpr auto get_template_wrapper( priority_tag<1> ) noexcept -> TemplateTypeList<C, Cs...> { return {}; }
+
+ template <typename...>
+ struct append;
+ template <typename T>
+ struct append<T> { using type = T; };
+ template <template <typename...> class L1, typename... E1, template <typename...> class L2, typename... E2, typename... Rest>
+ struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1..., E2...>, Rest...>::type; };
+ template <template <typename...> class L1, typename... E1, typename... Rest>
+ struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };
+
+ template <template <typename...> class, typename>
+ struct convert;
+ template <template <typename...> class Final, template <typename...> class List, typename... Ts>
+ struct convert<Final, List<Ts...>> { using type = typename append<Final<>, TypeList<Ts>...>::type; };
}
}
@@ -108,41 +137,28 @@ namespace Catch {
#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
-#define INTERNAL_CATCH_TYPE_GEN\
- template<typename...> struct TypeList {};\
- template<typename... Ts>\
- constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TypeList<Ts...> { return {}; }\
- template<template<typename...> class...> struct TemplateTypeList{};\
- /* Clang 20 and 21 cannot handle an explicitly specified all-pack template-template parameter here\
- ("conflicting deduction" regression, llvm/llvm-project#130778; fixed for Clang 22).\
- Remove get_template_wrapper once Clang 21 is no longer supported. */\
- template<template<typename...> class C, template<typename...> class...Cs>\
- constexpr auto get_template_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TemplateTypeList<C, Cs...> { return {}; }\
- template<typename...>\
- struct append;\
- template<typename...>\
- struct rewrap;\
- template<template<typename...> class, typename...>\
- struct create;\
- template<template<typename...> class, typename>\
- struct convert;\
- \
- template<typename T> \
- struct append<T> { using type = T; };\
- template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
- struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
- template< template<typename...> class L1, typename...E1, typename...Rest>\
- struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
- \
+#define INTERNAL_CATCH_TYPE_GEN \
+ /* We moved these into a central location and no longer create them
+ in each templated test's unnamed namespace, but we pull them in
+ with using to avoid qualifying all the references. */ \
+ using Catch::Detail::TypeList; \
+ using Catch::Detail::get_wrapper; \
+ using Catch::Detail::TemplateTypeList; \
+ using Catch::Detail::get_template_wrapper; \
+ using Catch::Detail::append; \
+ using Catch::Detail::convert; \
+ template<typename...> \
+ struct rewrap; \
+ template<template<typename...> class, typename...> \
+ struct create; \
+ \
template< template<typename...> class Container, template<typename...> class List, typename...elems>\
struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
\
template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
- struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
- template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
- struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
+ struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\