-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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
[libc++] Signature of complex pow
does not allow some user overloads
#109858
Comments
Per N4868 [cmplx.over]/3, I think we should implement the additional overloads like the following in C++20 and earlier modes (i.e. constrain them harder). template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type>
pow(const complex<_Tp>& __x, const complex<_Up>& __y) {
typedef complex<typename __promote<_Tp, _Up>::type> result_type;
return std::pow(result_type(__x), result_type(__y));
}
template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && 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));
}
template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const _Tp& __x, const complex<_Up>& __y) {
typedef complex<typename __promote<_Tp, _Up>::type> result_type;
return std::pow(result_type(__x), result_type(__y));
} Some crux in C++23
But the standard requirements was changed in C++23 by P1467R9, and IIUC that the type of For standard floating-point types ( |
Thanks @frederick-vs-ja I think the overloads you have make sense. Happy to make a PR for this. |
Not sure whether the "fix" would be preferred because the standard says that instantiating |
From cppreference I'm seeing
Which is fine because we specify what would happen for our type :) |
Thank you! |
…llvm#110235) Fixes llvm#109858. The changes in llvm#81379 broke some 3rd party library code that expected usability of `std::complex<NonFloatingPoint>`. Although such code isn't portable per [complex.numbers.general]/2, it might be better to make these additional overloads not to interfere overload resolution too much. --------- Co-authored-by: Louis Dionne <[email protected]>
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. stan-dev/math#3106
We can fix this by making the exponent's type
const&
, or by users callingstan::math::pow
fully instead of bringingpow
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, if a user has a custom type incomplex
this signature will be chosen by the compiler but then fail while calling__promote
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). It looks like the signature should be checking that__promote<_Tp, _Up>
is arithmetic so that users with custom types can add their ownpow
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.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 fixhttps://godbolt.org/z/1vE665xqT
The text was updated successfully, but these errors were encountered: