23

How do you restrict the allowed types in variadic templates and fold expression using C++20 concepts?

For example suppose I'd like to restrict the following fold expression to only support integral types, how would I do that?

#include <string>
#include <iostream>
#include <concepts>
using namespace std;

template<typename... Args> // requires (is_integral<Args>::value )
    int sum(Args... args) { return (... + args); }
int main()
{
    cout << sum(1,2,3);
}
Gonen I
  • 5,576
  • 1
  • 29
  • 60
  • Note that constraints can be an inferior alternative for such use cases. What do you win? Maybe better error messages. However, you lose flexibility, as you now can't sum doubles and ints, and you also can't apply it to overloaded classes. Without the constraint, the compiler will directly complain if the `+` can't be applied, so there is no real point in premature checking via a constraint what the compiler finds anyway. – davidhigh Apr 23 '22 at 15:08

2 Answers2

31

The minimal change to make it work is:

requires (std::is_integral<Args>::value && ...)

I'd also suggest using the less verbose is_integral_v<...> instead of is_integral<...>::value.

Or, even better, a concept:

template <std::integral ...Args> // no requires needed
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
23

You can use type-constraint auto syntax:

int sum(std::integral auto... args) { return (... + args); }
康桓瑋
  • 33,481
  • 5
  • 40
  • 90