Welcome to the world of compiler bugs! Your syntax is completely valid, yet only GCC can compile it.
So far, I tested with multiple clang, gcc and msvc versions.
Your variation with the function pointer raw array, only GCC parses it correctly. Clang 8.0.0 will crash, and MSCV will not compile it.
I tried two other variations: with a template alias and std::array
Function pointer alias template:
template<typename T>
using fptr = auto(*)(T const&) -> double;
template <typename T, typename = void>
constexpr fptr<T> my_temp[] = {
&details::X<T>, &details::Y<T>
};
template <typename T>
constexpr fptr<T> my_temp<T, enable_if_t<is_floating_point_v<decltype(details::X(T()))>>>[] = {
&details::X<T>, &details::Y<T>, &details::Z<T>
};
std::array
+ CTAD:
template <typename T, typename = void>
constexpr std::array my_temp = {
&details::X<T>, &details::Y<T>
};
template <typename T>
constexpr std::array my_temp<T, enable_if_t<is_floating_point<decltype(details::X(T()))>::value>> = {
&details::X<T>, &details::Y<T>, &details::Z<T>
};
To remove CTAD, simply use std::array<auto(*)(const vec&) -> double, 3>
.
Here's the results:
+------------+-------+-------+-------+
| Compiling? | GCC | Clang | MSVC |
+------------+-------+-------+-------+
| raw array | Yes | ICE | No |
+------------+-------+-------+-------+
| fptr alias | Yes | ICE | Yes |
+------------+-------+-------+-------+
| std::array | Yes | Yes | Yes |
+------------+-------+-------+-------+
Note that on the upcoming clang 9, it will be on par with GCC. All versions needs at least MSVC 2017. With workaround I'm sure it's possible to make it work with msvc 2015 too.
In the end, as long as it work on the platform you need right now, that would be okay. std::array
have a small compile time cost, but the raw array is surprisingly less portable as of right now.