Skip to content

[libc++] Are some standard overloads of std::pow missing? #110241

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

Closed
frederick-vs-ja opened this issue Sep 27, 2024 · 2 comments
Closed

[libc++] Are some standard overloads of std::pow missing? #110241

frederick-vs-ja opened this issue Sep 27, 2024 · 2 comments
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

Comments

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Sep 27, 2024

I'm referring to C++20/WG21 N4868 here, because the changes of additional overloads of std::pow introduced in C++23 by P1467R9 look defective and libc++ hasn't implemented P1467R9 yet.

In N4868 [complex.syn] there were 3 explicitly specified standard overloads of pow:

  template<class T> complex<T> pow  (const complex<T>&, const T&);
  template<class T> complex<T> pow  (const complex<T>&, const complex<T>&);
  template<class T> complex<T> pow  (const T&, const complex<T>&);

And then, several additional overloads were specified in N4868 [cmplx.over]/3, but their exact forms were not specified.

Currently, libc++ provides 4 overloads:

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) {
return std::exp(__y * std::log(__x));
}
template <class _Tp, class _Up>
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_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, 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));

If I understood correctly, only the first one is an explicitly specified overload, and the rest are additional overloads. So it seems that the remaining 2 overloads are missing.

However, when I attempted to added them during handling #110235, I found that it's very hard, if not impossible, to portably verify that these overloads are added. Because instantiating std::complex<NonFP> is unspecified and in some cases std::complex<std::complex<T>> would be instantiated when using braced-init-list due to the form of these overloads.
E.g. according to the current standard overload set, std::pow(std::complex<float>(1.0f), {1l, 1l}) would cause pow(const T&, const complex<T>&) (where T is complex<float>) to be detected, which in turn instantiates (probably nonsense) std::complex<std::complex<float>>.

It's not clear to me

  1. whether libc++ is effectively conforming now, i.e. lacking of these 2 overloads isn't observable in any conforming program, and
  2. whether there's any defect in the specification of explicitly overloads (effectively unchanged since C++20, see [complex.syn]) as they possibly cause std::complex<std::complex<T>> to be instantiated.

Edit: LWG3693 is somehow related.

@github-actions github-actions bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Sep 27, 2024
@ldionne
Copy link
Member

ldionne commented Oct 1, 2024

I think our overloads that use __promote might have been an undocumented extension we provided by mistake. I'd be curious to try removing them and replace them by the Standard ones.

I don't think it's possible to observe that we don't provide the overloads exactly as specified in the Standard, because those overloads are only enabled for arithmetic types and std::complex<T> can only be instantiated for T = {float, double, long double}. However, it might still be worth getting back in line with what the spec says.

@frederick-vs-ja
Copy link
Contributor Author

Closing as there at least shouldn't be observable differences. I remembered that I've submitted LWG3693 which is somehow related.

@frederick-vs-ja frederick-vs-ja added the question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead! label Oct 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. question A question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!
Projects
None yet
Development

No branches or pull requests

2 participants