<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/109858>109858</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[libc++] Signature of complex `pow` does not allow some user overloads
</td>
</tr>
<tr>
<th>Labels</th>
<td>
libc++
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
SteveBronder
</td>
</tr>
</table>
<pre>
Testing the Stan math library against clang 19.0.1 we found that one of libc++'s complex pow signatures is overriding one of our signatures. https://github.com/stan-dev/math/issues/3106
We can fix this by making the exponent's type `const&`, or by users calling `stan::math::pow` fully instead of bringing `pow` into the local scope. But I wanted to suggest a fix here that I think will stop this issue from coming up for other users.
In the `pow` signatures for a complex base and arithmetic exponent, such as the one below from [complex](https://github.com/llvm/llvm-project/blob/a4bf6cd7cfb1a1421ba92bca9d017b49936c55e4/libcxx/include/complex#L1109C1-L1113C2), if a user has a custom type in `complex` this signature will be chosen by the compiler but then fail while calling `__promote`
```c++
template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Up>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const complex<_Tp>& __x, const _Up& __y) {
typedef complex<typename __promote<_Tp, _Up>::type> result_type;
return std::pow(result_type(__x), result_type(__y));
}
```
This signature only checks that `Up_` is arithmetic while the compiler is looking for candidates, but then after that signature has been chosen it also requires that `_Tp` is arithmetic since `__promote<_Tp, _Up>` will throw a compiler error from it's static assert if both types are not arithmetic ([code](https://github.com/llvm/llvm-project/pull/81379/files#diff-d62c3ba6f0744bc0a5f7f2996847a72ba90af330f88e1251cc61d95974538c1eR32)). It looks like the signature should be checking that `__promote<_Tp, _Up>` is arithmetic so that users with custom types can add their own `pow` functions with custom complex types.
This could be fixed by adding another NTTP to these functions that checks if the result of `__promote` is valid.
```c++
template <class _Tp, class _Up,
__enable_if_t<is_arithmetic<_Up>::value, int> = 0,
__enable_if_t<is_arithmetic_promotable<_Tp, _Up>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const complex<_Tp>& __x, const _Up& __y) {
typedef complex<typename __promote<_Tp, _Up>::type> result_type;
return std::pow(result_type(__x), result_type(__y));
}
```
The example of the fix and issue can be found in the godbolt below. You can toggle the `SHOW_ERROR` macro on and off to see the current error and suggested fix
https://godbolt.org/z/1vE665xqT
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV1Fv47gR_jX0y2ANibJk68EPGyfGBdh2F9kcDn0SKGpksUuTPpKK4_76Ykg5VnLFoe0V6MsBRmLJ5PCbmW--GQrv1cEgbll5x8r7hRjDYN32e8AXvHPWdOgWre0u22f0QZkDhAHhexAGjiIMoFXrhLuAOAhlfACphTlAXi-zZQ5nhN6OpoMwiADWINiedkjG7-Jn7UHa40njK5zsGQiJCKNDD6A82Bd0TnV06LTXjm62aAlDCCfPis-M7xnfH1QYxnYp7ZHxvQ_CfOrwhfE9AWV8r7wf0TO-L_KsYtk9yz6nv78gSGGgV68QBuWhvcBR_Lj6iq8na9CEiDZcTgisyqQ1PjBesSpjfAfW0abRo_Mghda0l1UZYSB0xecIIX472TOrMuhHrS9AIUPRkWutU-Yw7ZvWKBNshKCtFBq8tCdcwt0Y4BHOwgTsIFjw4-GAPoCIDgzoMIX7kZwxP-CstAYf7Ck5F6MAvbNHCj0dOJ6gtw5sGNAlH5bz6DyaiOEGa5Yl2ifeUtgKjyBMB8KpMBwxKDmL3g78KAcQPpqjhLao7TlBYeXdZIWV94xvfiexWr9c_306Oft3lIHxfatty_herNq-kt1a9m0u8hXPW1HzVoq6y_J1u6rropJliSsyoFr5-kq8MFKPHTK-v0LgxZc8z-pd_ulLnufFjjNekwOqBxEjBIPw5Pjogz0mUiiTeJEsVFmK9lusUhpaBDlYj4boQmGg9Uqjg3YM9MJAL5SG86A0zpnUNCdnjzYgEW6WHHqMn2tJxbcBjyctAgIrdlIL76F5PpED08PP8aFp0IhWY6P6JrBip3xzSxwrdrSseEisfRF6xBgCE1jxAKy4h4x-jecpo5VBaL483u2-fWt-erx_aPZPX__SfL57vLKDFTuKkxFHhJs3xW5CNj-M1tEhxDe-iaU2s0IbigfGK2ia1-hUXBCdoncXxmtg6ykUELPTYf8HcDj0ow5Nenyz6zCMzoAP3a2w-Wa-lm8iwkidj-8v8X39Zo-t7z9kdJ7m5_dcskZfQA4of_hU66zKfj41UTP8vPoSj94RTXnQ1kZ1o-qVwnSqE4GEcXdjoegDumT7diyRvkU0Vw6rAEJ7Cw5_HRXJwRULxfI3WLwyEt9z-WPUqyyVSRicPU_CEkGjc9YlpVBJiH0QZFR4jy5QYbY2DDHXdCiCsWF-OOObKDEd_pf6chq1Zny_yYt1zfi-V5oiVnSq7z91FZdFK6o-W69WrcxE2a97XtfVZrUWa96KOhN9UWT9ZoM5L3Mpq7yry3q9KouNzPGpSAJTL-ExxOx40OpHStwt_H6wo-6ShqCc-tMU8N8L6Yc02LQrNauzCsNcxnzshKKjlo3KgT2bmfL3o5FBWfN-31X-4_7lb2grr6h79YodCZ_oYk8XJrWcvz4_f4PU6TzOzogwJ5arPgYjVRG1yw-aSE6-CK265f9KHacy_-MiyXf_jqnJF_r9X4vRnwr8f1ZgmgQFOUD0IzLSuEXTTpqoqG7a67yr0sx0sF1rdUiDzhL-Zse4LNjDYZJlVmXff_r6S_Pw9PT1iXh8FNJZsCZatn0fJzycNHx0Dk2Y1JAWTLMfdgRmDveDviUcS-sOjO__wfg-f3moqvL11-dFty26uqjFArf5mq95tqnLbDFse8xIyCrZZpuqLOq6xHVWtGspSlms8mqhtjzjq6zmK57lZZktS44ckWf5qitXvFqzVYZHofSSpJTOXsRIbfOs3pSbhRYtah-vHZzPLwWcriFuGwW4HQ-erTKtfPA3O0EFHS8ss23lPXy_Ncg3ss3Uq7PoU1_QNHd6e8Q0zNE9Q1vR-cXo9PY_bg1v94rJsZct_2cAAAD__1ExTvU">