Why does the parameter pack not work as expected in concepts?

Why does the parameter pack not work as expected in concepts?
typescript
Ethan Jackson
template<typename T, typename... Args> inline constexpr auto c = sizeof(T) + sizeof...(Args) > 1; template<typename... Args> requires c<Args...> // ok void f1() { } template<typename T, typename... Args> concept C = sizeof(T) + sizeof...(Args) > 1; template<typename... Args> requires C<Args...> // error: Pack expansion used as argument // for non-pack parameter of concept. void f2() { } int main() { f1<int>(); // ok f2<int>(); // error }

See https://godbolt.org/z/GEWfoqdG9

Why is f1<int>() ok, but f2<int>() ill-formed?

What I want to know is not how to make the code work, but the rationale behind the restrictive rule that a concept cannot take a parameter pack as its parameter list, while other temploids can.

Answer

I think this does what you intended:

template<typename... Args> concept C = (sizeof(Args) + ...) > 1;

That's a fold expression to get the total size of the Args types.

Your original sizeof(T) + sizeof...(Args) was probably a mistake: it's the size of T in bytes plus the number of elements in the pack Args.

You can also simplify the usage by not using requires:

template<C... Args> void f2() { }

Related Articles