Skip to content

Commit

Permalink
Merge branch 'cpp-variadic-template' into cpp-template-2
Browse files Browse the repository at this point in the history
  • Loading branch information
joka921 committed Feb 11, 2025
2 parents 97a6fb3 + acc9eab commit 83c25c3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/backports/concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@
#define QL_CONCEPT_OR_TYPENAME(...) typename
#define CPP_template_2 CPP_template_2_SFINAE
#define CPP_and_2 CPP_and_2_sfinae
#define CPP_variadic_template CPP_template_NO_DEFAULT_SFINAE
#else
#define QL_CONCEPT_OR_NOTHING(...) __VA_ARGS__
#define QL_CONCEPT_OR_TYPENAME(...) __VA_ARGS__
#define CPP_template_2 CPP_template
#define CPP_and_2 CPP_and
#define CPP_variadic_template CPP_template
#endif

// The namespace `ql::concepts` includes concepts that are contained in the
Expand Down
21 changes: 21 additions & 0 deletions src/backports/cppTemplate2.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@
#pragma once
#include <concepts/concepts.hpp>

// The internal reimplementation of a `CPP_variadic_template` macro
// that can be used for variadic template functions.
#define CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_0(...) \
, std::enable_if_t<CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__), \
int> = 0 > CPP_PP_IGNORE_CXX2A_COMPAT_END

#define CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_3_requires

#define CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_WHICH_(FIRST, ...) \
CPP_PP_EVAL(CPP_PP_CHECK, \
CPP_PP_CAT(CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_, FIRST))

#define CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_(...) \
CPP_PP_CAT(CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_, \
CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_WHICH_(__VA_ARGS__, )) \
(__VA_ARGS__)

#define CPP_template_NO_DEFAULT_SFINAE(...) \
CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
template <__VA_ARGS__ CPP_TEMPLATE_NO_DEFAULT_SFINAE_AUX_

// The internal reimplementation of a `CPP_template_2` and `CPP_and_2` macro
// that can be used for class members when the outer class has already been
// constrained using `CPP_template`.
Expand Down
15 changes: 12 additions & 3 deletions test/backports/ConceptsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
// Created by kalmbacj on 2/10/25.
//

#include <gmock/gmock.h>

#include "backports/concepts.h"

template <typename... T>
CPP_concept Something = (... && (sizeof(T) <= 4));

// Those are rewritten as follows:
// A templated class with a variety of members.
CPP_template(typename T)(requires(Something<T>)) struct C {
// A constructor that takes an int only exists for certain `T`
explicit constexpr CPP_ctor(C)([[maybe_unused]] int i)(
Expand All @@ -17,8 +19,10 @@ CPP_template(typename T)(requires(Something<T>)) struct C {
// type `F`.
CPP_template_2(typename F)(requires Something<F>) void f(F arg) { (void)arg; }

// Same, but the constraint combines F and T.
CPP_template_2(typename F)(requires(Something<F, T>)) auto i() {
// Same, but the constraint combines F and T. Note that you have to use
// `CPP_and_2` instead of `CPP_and`.
CPP_template_2(typename F)(
requires Something<F> CPP_and_2 Something<T>) auto i() {
} // Additional template parameter + `auto`

// Member function with explicit return type that has no other template
Expand All @@ -30,3 +34,8 @@ CPP_template(typename T)(requires(Something<T>)) struct C {
// arguments but poses additional constraints on `T`.
CPP_auto_member auto CPP_fun(h)()(requires Something<T>) {}
};

// A variadic function template. NOTE: you currently have to use plain `&&`,
// the `CPP_and...` macros won't work here.
CPP_variadic_template(typename... Ts)(
requires(Something<Ts...>&& Something<Ts...>)) void f(Ts...) {}

0 comments on commit 83c25c3

Please sign in to comment.