<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/76450>76450</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [libc++] Const valarray (g)slice, mask, etc. fail to match valarray in template functions
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          yihuajack
      </td>
    </tr>
</table>

<pre>
    Reproducer:
```c++
#include <iostream>
#include <valarray>

template<typename T>
void foo(const std::valarray<T> &va) {
    std::cout << va[0] << '\n';
}

int main() {
    const std::valarray<bool> vmask = {1, 0, 0, 1};
    const std::valarray<std::size_t> vind = {1, 3};
    const std::valarray<double> va = {1, 2, 3, 4};
    foo(va[std::slice(1, 2, 1)]);
    foo(va[std::gslice(0, {1, 1}, {1, 1})]);
    foo(va[vmask]);
    foo(va[vind]);
}
```
The code can be successfully compiled by Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33130 and v19.latest for x86/x64 but failed to be compiled by clang 17.0.6 or (assertions) trunk.
If function `foo()` is not a template function, i.e.,
```c++
void foo(const std::valarray<double> &va) {
    std::cout << va[0] << '\n';
}
```
Then the code compiles.
According to [std::valarray<T>::operator[]](https://en.cppreference.com/w/cpp/numeric/valarray/operator_at):
```c++
std::valarray<T>       operator[]( std::slice slicearr ) const;  // (3)
std::slice_array<T>    operator[]( std::slice slicearr );  // (4)
std::valarray<T>       operator[]( const std::gslice& gslicearr ) const;  // (5)
std::gslice_array<T>   operator[]( const std::gslice& gslicearr );  // (6)
std::valarray<T>       operator[]( const std::valarray<bool>& boolarr ) const;  // (7)
std::mask_array<T>     operator[]( const std::valarray<bool>& boolarr );  // (8)
std::valarray<T>       operator[]( const std::valarray<std::size_t>& indarr ) const;  // (9)    
std::indirect_array<T> operator[]( const std::valarray<std::size_t>& indarr );  // (10)
```
>The const overloads that return element sequences create a new std::valarray object.

If the valarray is not const, then it returns a std::valarray<T>, std::gslice_array<T>, std::mask_array<T>, or std::indirect_array<T>, which makes no dissent - the compiler refuses to match std::valarray<T> with it. However, it is not the case for a const valarray:

>3,5,7,9) A std::valarray object containing copies of the selected items.

>For overloads (3,5,7,9), The function can be implemented with the return type different from std::valarray. In this case, the replacement type has the following properties:
- All functions accepting an argument of type const std::valarray& except begin() and end()(since C++11) should also accept the replacement type.
- All functions accepting two arguments of type const std::valarray& should accept every combination of const std::valarray& and the replacement type.

According to the Working Draft, Standard for Programming Language C++ (N4950):
>Any function returning a valarray<T> is permitted to return an object of another type, provided all the
const member functions of valarray<T> are also applicable to this type. This return type shall not add
more than two levels of template nesting over the most deeply nested argument type.
4 Implementations introducing such replacement types shall provide additional functions and operators as
follows:
(4.1) — for every function taking a const valarray<T>& other than begin and end (28.6.10), identical functions
taking the replacement types shall be added;
(4.2) — for every function taking two const valarray<T>& arguments, identical functions taking every combi-
nation of const valarray<T>& and replacement types shall be added.

For libstdc++, the replacement types (`mask_array` is an exception - the operator function directly returns a `valarray`, so it compiles) are
- `_Expr<_SClos<_ValArray, _Tp>, _Tp>`
- `_Expr<_GClos<_ValArray, _Tp>, _Tp>`
- `_Expr<_IClos<_ValArray, _Tp>, _Tp>`

For libc++, the replacement types are
- `__val_expr<__slice_expr<const valarray&> >`
- `__val_expr<__indirect_expr<const valarray&> >`
- `__val_expr<__mask_expr<const valarray&> >`
- `__val_expr<__indirect_expr<const valarray&> >`

which refuse to match `const std::valarray<T> &`, which might be a violation of the C++ standard.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WFtv6zgO_jXqC3EMR06c5CEPPWmzW2BvmDmYfSxkmUk0lSWvJKen8-sXlGzn1tvsnNmicBJLIj-SHy-28F7tDOKKzb6y2d2N6MLeutWL2nfiVyGfbipbv6x-wtbZupPoWHHL8juW37IyT_-S8a_0n-7yQhmpuxqBFWtlfXAoGlbcv7Z8EFo4J16Oy_EasGm1CMiKdXhp0YgG4du452BVDVtrGV9Ia3wAH2oCVdwexa1pOzBeHgTjS2DzHh0AHLdL2wVCwYo1HASbfc3Z7G64wficzdaGPorBtPndKUplAjRCGcYXVzreBlZZqwnboRH-CVhxRwcnjK8hHy8T0lR8Stx4z6vf8DFEycrUZ4KLz4urbVdpjFLEmQyeBPE1TC-lpVBEBx7RaCWR8cXx7ITxJZvd0fWjw7vhdHTGgCA65er3BzKjlz_Yokx9seMY6IHi6ee3PYK0NYIUBioE30mJ3m87rV9A2qZVGmuoXuDvSjrr7TYA44ufiB1rxjfrlCfwzzaoRv2mzA7W6ZCDX9B5ZQ1MllmxyIpiUuQgTA2HyTKjVPABttbB90XJ-OZ7OYWqC7AVUWGwBOZUv9TC7GAyz_KsBOsIhfAeXVDWeIITXGeesmTVwxa2nZG0BqzMk2vIHWUOyoOxAQQMKTlupRCoDDPG1--Vg08l65F1f1rGXgXSQBijmTzne3_cSmldTdEJFk55eVFe0k3bohPBulQ9I5EW-xBaT8t8w_gGTSbb1uEWHRqJmbQN45tnxjeybRnfmK5BpyTjm1EB3wxiH0WIzHy35r5ZANPfBUS-gPM8hXgVjniyTMWBFV8BEnwiT0EYzlXFM4-X2n6Xqgsl02sln7XnglpDASlh96Fps2utu1dt-1-1Xugrf5iV102FdNPX9-ydX-unGnkVyR-g_0Lz4s-w_Lr_EQhl6vd8sIxILsEoUyuHMpy74keCuYAxyUePXNQnVtynXkOa7AGdtqL2EPYigMPQOQOosUETwON_OiorHqRDKtACDD5fwwNb_YoyZKcTzMM2FsFxS1_tk8v4mhYNqEGlB_HmqEW738ufs_UrvtGqdfB-JGjT817JPTTiCQkp1Mp78sGXvpb3vdThtvPoqXw3Isj92wPiswp7UCGDv9pnPKCLTS0MfohChcfYeUUfjaOI21NXsuKepqMZ4-s542tiGNy-GQWSFYQy1GSkbRV6sCkWHjXKgDWogI3PLlRsrDuhQyrMZzrJAGLO2ND7SUU1beIL1slo0tUziUZsqNU29qcAW2eba-AZPFDHVD56pCcHOGy1kImIUcxe-LiwtVrbZzKvdZRBQaEfPfYFbrUeIXoQUmIbaLMwINyui_LIISTyrXTjJeB3OggV7sYpnGYmNHU_wfCFV0Yi9JPXhIZQ8Hvb6RqE9rZX_aot2Udgw7Md0frPwB0UJ53Etzg1VsqIGCu7fe80WfYOzldmF9r9b-ue6OedE9uY0z8HQfWojqT-l7M7J5qGdvxNmF0ndqOziF7_mC5n-dn8UdzfmpcjvRKFYujgMrmUhxZdo0JIM2pPN2GGJLBbEMaGPbpoCKFrnT2oGik6mvAnrckrDTYVupNQ2O2VTuGwD2zbaiVFpTF5QvnkLPhGX0-Z7_ekK065dZ30NdYhFVsTY6zxgDoFeBiCDfpIAcrF6ObG-gA1Yqtf4iJZMBD5JEhTeBgSUSQblAnxuZqk-U7ur8Lre4C9ZwikoqPijJSmHhuVB-GTtpSEx7yjGSuLKcDuOVvkbDmNLEhMHGMaxFMK6GXB68twCX3M9rG27JQZso4owxdZmaXORsW0RhOUPAXbP-InJa8RerC4isZifZzmCT__LH4K3ZsWjHn7BshByEmSfkkgLnP1NeGm_tCos6ylsq5V5UM9jPVv1NdY81mZn3TQ9JAmTF8MCVtqhwMfjo5JTVW_nPRzVuajAWV83PaWOuDwSBRLqsOhFLIyf7z_3jpWrB9_Xmvr6csvQt-mIrWGx29t36r7b8NEc372L3_g7MPvOnvm4A-9e2Hq40HoR-z1Pqappv95EXxexqfXK9DnEsa55o8IibH_v6JI1zR7pdnqOFrRo-iHL-F6avXTm9rtQ8wDOCirx3SiiAytx_dNKrupV0W9LJbiBleTeV6Uy2lZTG72KxS45POiXkheVrwuq8WcV3U1n063k9lc1DdqxXNeTDifT8oiLybZYjaRk2LJZ7Na5tOJZNMcG6F0pvWhyazb3SjvO1zNy-ksv9GiQu3jO1HOT6nD2ezuxq3o0Jeq23k2zbXywR_FBBV0fJt6cmx2B-szN1Mi7xhf9s-Ma4gvqvgaMMgsvtg5-vg4n5vr9zD-pnN6df7GYafCvqv6Fw2Eq__40jpLnZfxTbTVM76J5v43AAD__2_gxk4">