2

I'm trying to use std::size instead of macros like _countof or ARRAYSIZE, but I'm running into scoping problems.

Is the following code legal?

#include <iterator>

int main()
{
    int arr1[4];
    auto f = [](int(&arr2)[std::size(arr1)])
    {
        arr2[0] = 1;
    };
    (void)arr1;
    (void)f;
}

GCC and MSVC compile it fine, but Clang complains:

error: variable 'arr1' cannot be implicitly captured in a lambda with no capture-default specified
    auto f = [](int(&arr2)[std::size(arr1)])

Which one is correct?

5
  • 1
    clang is wrong, arr1 is not captured because it is not evaluated. define a separate constexpr auto size_arr1 = std::size(arr1); and then use it in the lambda to convince clang Commented Apr 22, 2023 at 19:49
  • @n.m. std::size(arr1) does not appear in an unevaluated operand, so it is potentially-evaluated and arr1 is odr-used. I think the question is rather whether or not the odr-use is allowed in the parameter of the lambda (with or without implicit/explicit capture). Commented Apr 22, 2023 at 19:55
  • @n.m.: What about this? Commented Apr 22, 2023 at 19:56
  • you are right I was not reading it carefully enough. Commented Apr 22, 2023 at 20:42
  • There are no errors with clang 16. I also tried with c++2a. Commented Apr 22, 2023 at 21:49

1 Answer 1

2

I think Clang is correct.

(Using terminology from the current C++23 draft.)

std::size(arr1) is not part of an unevaluated operand, so the expression arr1 is a potentially-evaluated id-expression naming the variable arr1. The expression is also not part of a discarded-value expression, nor is the variable arr1 usable in constant expressions. Therefore the expression odr-uses arr1. (The variable could be made usable in constant expressions, making arr1 not an odr-use, by adding constexpr on it.)

However, being a variable with automatic storage duration, arr1 is a local entity that is not odr-usable in the scope in which the expression appears. Specifically, to be odr-usable inside a lambda a local entity must be captured by the lambda, which arr1 is not. Even with a capture however, CWG 2380 clarifies that the local entity is odr-usable only in the block scope of the lambda, not in the function parameter declaration clause.

A program that odr-uses a local enitity in a scope in which it isn't odr-usable is ill-formed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.