Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arrays of variable templates cannot deduce their lengths from pack expansion in the initializer #79750

Open
Mq-b opened this issue Jan 28, 2024 · 5 comments
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@Mq-b
Copy link

Mq-b commented Jan 28, 2024

#include <iostream>
#include <type_traits>

template<std::size_t...values>
constexpr std::size_t array[]{ values... };

int main() {
    std::cout << std::is_same_v<decltype(::array<1, 2, 3, 4, 5>),  const std::size_t[]>;
}

Output:

1

Both gcc and clang have this result, but this is obviously not true, msvc outputs 0.

gcc and clang consider array<1, 2, 3, 4, 5> to be the same type as const std::size_t[].


msvc will only output 1 when faced with the following code.

#include <iostream>
#include <type_traits>

template<std::size_t...values>
constexpr std::size_t array[]{ values... };

int main() {
    std::cout << std::is_same_v<decltype(::array<1, 2, 3, 4, 5>), const std::size_t[5]>;
}

msvc considers array<1, 2, 3, 4, 5> and const std::size_t[5] to be of the same type.

  • I think msvc is right.
@Mq-b Mq-b changed the title The variable template type is incorrect Arrays of variable templates cannot deduce their lengths from pack expansion in the initializer Jan 28, 2024
@frederick-vs-ja
Copy link
Contributor

Curiously, sizeof(::array<1, 2, 3, 4, 5>) correctly works for Clang (reports 40 for this case on an x64 platform).

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed new issue labels Jan 28, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 28, 2024

@llvm/issue-subscribers-clang-frontend

Author: mq白 (Mq-b)

```cpp #include <iostream> #include <type_traits>

template<std::size_t...values>
constexpr std::size_t array[]{ values... };

int main() {
std::cout << std::is_same_v<decltype(::array<1, 2, 3, 4, 5>), const std::size_t[]>;
}


[Output](https://godbolt.org/z/E8jTW1GsW):

1

Both gcc and clang have this result, but this is obviously not true, msvc outputs **0**.

gcc and clang consider `array&lt;1, 2, 3, 4, 5&gt;` to be the same type as `const std::size_t[]`.

---

msvc will only output 1 when faced with the following code.

```cpp
#include &lt;iostream&gt;
#include &lt;type_traits&gt;

template&lt;std::size_t...values&gt;
constexpr std::size_t array[]{ values... };

int main() {
    std::cout &lt;&lt; std::is_same_v&lt;decltype(::array&lt;1, 2, 3, 4, 5&gt;), const std::size_t[5]&gt;;
}

msvc considers array&lt;1, 2, 3, 4, 5&gt; and const std::size_t[5] to be of the same type.

  • I think msvc is right.

@Mq-b
Copy link
Author

Mq-b commented Jan 28, 2024

Curiously, sizeof(::array<1, 2, 3, 4, 5>) correctly works for Clang (reports 40 for this case on an x64 platform).

You're right, clang and gcc behave differently here, clang can sizeof(array<1,2,3,4,5>) and get 40.

If it is gcc, it is a compilation error.

#include <iostream>
#include <type_traits>

template<std::size_t...values>
constexpr std::size_t array[]{ values... };

int main() {
    std::cout<<sizeof(array<1,2,3,4,5>);
}

https://godbolt.org/z/aMbGGzfGd

@shafik
Copy link
Collaborator

shafik commented Jan 30, 2024

This does look like a bug but not 💯 sure

CC @erichkeane @Fznamznon

@beached
Copy link

beached commented Feb 27, 2024

I found this case, originally as a class static variable, but reduced to

enum class Values { A, B, C };


template<typename E>
inline constexpr Values values[] = {Values::A, Values::B, Values::C};

constexpr auto r = values<Values>[0] == Values::A;

Fails with

<source>:10:20: error: constexpr variable 'r' must be initialized by a constant expression
   10 |     constexpr auto r = values<Values>[0] == Values::A;
      |                    ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:10:24: note: read of element of array without known bound is not allowed in a constant expression
   10 |     constexpr auto r = values<Values>[0] == Values::A;
      |                        ^
1 error generated.
Compiler returned: 1

But

enum class Values { A, B, C };


inline constexpr Values values[] = {Values::A, Values::B, Values::C};

constexpr auto r = values[0] == Values::A;

works. Both work in msvc/gcc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

6 participants