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() {
}