Well, that was strangely easy.
#include <concepts>
#include <cstddef>
#include <type_traits>
template<int N, template<int> class X>
concept Fooable =
requires(X<N> a, int i) { a[i]; } &&
(
N == 1 ||
requires(X<N> a) { a.reduce(); }
);
template<int N, template<int> class X>
requires Fooable<N, X>
void foo(X<N>) {}
template<int N>
struct Myx1 {
int operator[](int) { return 0; };
};
template<int N>
struct Myx2 {
int operator[](int) { return 0; }
int reduce() { return 0; }
};
int main() {
foo(Myx1<1>{});
foo(Myx1<2>{}); // error - no reduce() and N != 1
foo(Myx2<2>{});
}
The ||
operator in concepts is short-circuiting, just like normal operator, so N == 1 || something
works as expected.
CLICK HERE to find out more related problems solutions.