2

I wanted to constrain the number of the template type to be less than 3. I expected F(1,2,3) to not compile but it actually did and printed 3.

template <typename ...Ts>
concept LessThan3 = requires {
  sizeof...(Ts) < 3;
};

template <typename... Ts>
requires LessThan3<Ts...>
void F(Ts... ts) {
  cout << sizeof...(ts);
};

int main() {
  F(1, 2, 3);  // Compile
}

However, if I explicitly put the sizeof...(Ts) < 3 in the function declaration, F(1,2,3) won't compile, work as expected.

template <typename... Ts>
requires(sizeof...(Ts) < 3) void F(Ts... ts) {
void F(Ts... ts) {
  cout << sizeof...(ts);
};
// F(1,2,3) doesn't compile, expected.

What's the correct way of require a concept?

WL_Law
  • 87
  • 7
  • The *requirement-seq* enclosed in brackets are not described to be Boolean predicates, but satisfiable syntax constraints. [Reference](https://en.cppreference.com/w/cpp/language/requires) – jxh Jul 16 '23 at 01:29
  • I'll share a question which really helps clearing up these `requires` things for me: https://stackoverflow.com/q/54200988/3966456 – Weijun Zhou Jul 16 '23 at 01:49

2 Answers2

4

To add on to others' answers, you can actually simplify your concept requirement by doing this:

template <size_t Size>
concept LessThan3 = (Size < 3);

template <typename... Ts>
    requires LessThan3<(sizeof...(Ts))>
void F(Ts... ts) {
  std::cout << sizeof...(ts);
};

You would see that if you passed two parameters, it works. But, if greater than two, it has a compilation error that says it doesn't satisfy LessThan3.

Amolgorithm
  • 697
  • 2
  • 20
1

sizeof...(Ts) < 3 itself does nothing, the computed result is ignored. It should be

template <typename ...Ts>
concept LessThan3 = requires {
  requires sizeof...(Ts) < 3;
};

Similar: N < 3 vs. static_assert(N < 3).

273K
  • 29,503
  • 10
  • 41
  • 64