Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the syntax for the 'requires' expression of a variadic template with contraints?

If I have a variadic template along the lines of;

template<typename T>
concept Fooable = requires (T t) { t.bar() -> bool; };

struct Foo {
  int big_foo;

  template<std::Integral T, Fooable ... U>
  explicit Foo(T&& i, U&& ... f) noexcept
    : big_foo {std::forward<T>(i)}
  {
    Something::something(std::forward<U>(f)...);
    ...
  }

};

then the definition of the template and its constraints works as expected.

But if I 'require' more constraints on Foo and so use the 'requires' expression format, such as;

  template<typename T, typename ... U>
    requires std::Integral<T>
          && Fooable<U> && BillyBobable<U> // WHAT GOES HERE? ELLIPSIS... BUT WHERE?
  explicit Foo(T&& i, U&& ... f) noexcept
    : big_foo {std::forward<T>(i)}
  {
    SOMETHING::something(std::forward<U>(f)...);
    ...
  }

Then: What do I use as the syntax for the variadic U to expand it in the expression?

like image 382
David H Parry Avatar asked Jan 26 '23 00:01

David H Parry


1 Answers

You can use the usual C++17 fold-expression syntax here:

template<typename T, typename ... U>
  requires std::Integral<T>
        && ((Fooable_concept<U> && BillyBobable_concept<U>) && ...)
explicit Foo(T&& i, U&& ... f) noexcept

Or, you can go back to your earlier syntax by introducing a new concept that merges the two:

template <typename T>
concept FooAndBillyBob = Fooable_concept<T> && BillyBobable_concept<T>;

template <std::Integral T, FooAndBillyBob ... U>
explicit Foo(T&& i, U&& ... f) noexcept

Note: Please don't name your concepts *_concept

like image 61
Barry Avatar answered Jan 31 '23 23:01

Barry