In the following example, the function arguments are used to test with a requires expression whether an expression using them is well formed. The requires expression takes no arguments; it uses the variables in the function scope directly:
#include <cstddef>
#include <vector>
template<typename T>
void Resize(T &v, std::size_t const n)
{
if constexpr (requires { v.resize(n); })
v.resize(n);
}
template<typename T>
void Eziser(T &v, std::size_t const n)
{
if constexpr (requires { v.eziser(n); })
v.eziser(n);
}
int main()
{
std::vector<int> v;
Resize(v, 10u);
Eziser(v, 10u);
}
The above code compiles with the Clang concepts branch. However, GCC10 only accepts the call to Resize
. GCC9 ICEs. Is Clang right at accepting it?
Yes, a requires-expression can use anything that’s in scope. It needs only the type of anything it names, after all, except in a nested-requirement or other constant expression. That’s true of surrounding declarations just as much as of its own (formal) parameters.
C++20 explicitly mentioned this in [expr.prim.req]/5:
The requirement-body contains a sequence of requirements. These requirements may refer to local parameters, template parameters, and any other declarations visible from the enclosing context.
This, however, was merely a restatement of general rules, so has since been removed.