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

    <tr>
        <th>Summary</th>
        <td>
            std::ranges::set_union won't compile with custom projections of different types
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

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

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

<pre>
    the following code doesn't compile

```cpp
#include <algorithm>
#include <string>
#include <vector>

struct S
{
    int i;
    std::string s;
};

struct M
{
 M(int);
    M( const S& );
};

auto set_union( const std::vector<int>& vi, const std::vector<S>& vs )
{
    std::vector<M> vm;
    std::ranges::set_union( vi, vs, std::back_inserter(vm), std::less{}, std::identity{}, &S::i );

    return vm;
}
```

the implementation of `std::ranges::set_union` simply forwards to `std::set_union` providing a comparison wrapper like this
```cpp
auto __ret = std::__set_union<_RangeAlgPolicy>(
 ranges::begin(__range1),
        ranges::end(__range1),
 ranges::begin(__range2),
        ranges::end(__range2),
 std::move(__result),
        ranges::__make_projected_comp(__comp, __proj1, __proj2));
```
the comparison operation in `std::set_union`, like in any algorithm, is called both ways:
```cpp
__comp(*__it1, *__it2)
```
and
```cpp
__comp(*__it2, *__it1)
```

which makes the wrapper apply `__proj1` to both `*__it1` and `*__it2`. the same is true for `__proj2`. it causes no problem if both projections are `std::identity` but won't compile with custom projections.

`std::ranges::merge` compiles just fine in this case.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVdGOozoM_Zr0xdoKQgvlgYfZzvZtpKs7H4ACuJCdkKDEtOrfXwVogZ3p7l6polFsnxwf24lwTtYaMWP772z_uhE9NcZm2FlH5rIpTHXLqEE4G6XMVeoaSlMhVAadZjwhKE3bSYUseGXBy_SNg_FXdt20wyOpS9VXCCw6ClUbK6lpWfTjK7sjK3X9xHjBkoydjcPXke1LgvdpL_k-LgAApCaQLFrsOKpY9MKil_EccA8rS17n9RL47VfgN8YPUhPj6Qrab0NptPNceAxL-2dw0ZMBh5T3Who9hz4I3nM9-qOiHx7xIhk_PvV7v3u54ejPanwOeWPRD7i0Xytkha7RTWotiY40Ls5_H96FKD9yqR1aQsv44dJ6EksPhc55PsnraltWqEnSbTYxHr9PtrWID44Wqbd6ydyHrvtvGeObWLadwhY1CZJGgzkDi4M_JBsH4HzcDc7GXoWtHJBZxa18O2susvJtJYbREFY6o-FqRdehBSU_EKiR7tmkDD2R5xYJWPQ6S5Tn8zHRMf_Xc31R9T9GyfI2VP0wabNMo8Ba-nrl-bAbjvWYRRyEXPijrp55_waW_y_YtfcjwdZccHRC1yv6E2Set-ID886an1gSVrkXe4gfF0fIB2M4L8eDF720bhPfIIuKmQ7t2CZSPy23Bx9KKjUIfYP5ZuNHkA5KoRRWUBhq4CpuA_cnhb8TPzD-kueSwnEMhjWfh3nNWejqb_H4Ai98hjd-r40sG_D6OvCq3JtXdH4MWBzcpY0DPwtDdoMYE3gcgNDVYouzONgOUE606IUh2_s3xc5oo48kKEXv0IE2fpYKhS3I83jGVGxptANhcVWVxxUSB1D0BFezep7gKqmBsndk2iXO9pd368vLoEVboweewBz87B3BWeqh8H6coRQOt5sqi6o0SsUGszBOo2AXpzzZNJnYh3gOz0WwOxzSfXpOUKTIwyhJcJfG-2ojMx7wKDjwOAx2h12yDTGKi0NQ8jBN0igN2S7AVki1VerSbo2tN9K5HrN4HwTJRokClbu_4TbzTt-KvnZsFyjpyM1hJElh9vtL72_V8zdoJc9ntKgJ6Nah2_RWZQ1RN2DyE-OnWlLTF9vStIyfPI_p79uExPhpyMUxfhrS-S8AAP__QniLHA">