Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are requires expressions allowed to "capture" variables of the enclosing scope?

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?

like image 662
metalfox Avatar asked Nov 05 '19 09:11

metalfox


1 Answers

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.

like image 188
Davis Herring Avatar answered Oct 20 '22 17:10

Davis Herring