Issue 76450
Summary [libc++] Const valarray (g)slice, mask, etc. fail to match valarray in template functions
Labels libc++
Assignees
Reporter yihuajack
    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.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to