Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does MSVC refuse to compile `static_assert(std::size(arr) < N)` when [array] `arr` declared thread local?

Tags:

c++

visual-c++

Attempting to compile some example.cpp containing the following:

#include <array>

void test() {
    thread_local int arr[10];
    static_assert(std::size(arr) < 100);
}

MSVC 19.35.32215 tells me:

1>example.cpp(5,34): error C2131: expression did not evaluate to a constant
1>example.cpp(5,29): message : failure was caused by non-constant arguments or reference to a non-constant symbol
1>example.cpp(5,29): message : see usage of 'arr'

The same snippet not containing the thread_local specifier, compiles just fine.

For reference, this is Visual C++ where I have experimented with trying to enforce standard compliance (/std:c++20), and /sdl is used as well -- these changes do not eliminate the compilation error. Also, http://godbolt.org gives me the same error when using MSVC "latest", but, more importantly, latest Clang, for instance, compiles the otherwise problematic snippet just fine.

I don't know how to get the full cl command line as used by the IDE when building my solution through the Visual Studio 2022 GUI I am using, but I do get the same compilation error if I drop to a VS developer command prompt environment and invoke cl directly: cl /c example.cpp (with or without /std:c++20) gets me the same error, basically:

Microsoft (R) C/C++ Optimizing Compiler Version 19.35.32215 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

example.cpp
example.cpp(5): error C2131: expression did not evaluate to a constant
example.cpp(5): note: failure was caused by non-constant arguments or reference to a non-constant symbol
example.cpp(5): note: see usage of 'arr'

I fail to see why thread-local storage for arr should prevent the compiler from deducing its size given the declaration, and subsequently perform static_assert as expected? Am I missing some subtle property of modern C++ here?

like image 350
amn Avatar asked Aug 12 '26 19:08

amn


1 Answers

This seems to be a MSVC bug. The code is fine and should compile. The storage duration of arr should be irrelevant. As suggested in the comments under the question, you should report it.

Just referencing a non-constexpr variable of object type doesn't cause an expression to not be a (core) constant expression and you are neither applying an lvalue-to-rvalue conversion to arr or its subobjects, nor are you producing a pointer or lvalue to it or any of its subobjects as a result of the constant expression. The result of std::size(arr) is only dependent on its (deduced) template argument.

like image 59
user17732522 Avatar answered Aug 15 '26 10:08

user17732522



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!