Visual Studio 中的模板化函数指针数组
Guillaume Racicot 对 这个问题关于如何专门化模板变量.但我在 visual-studio-2017 创建函数指针的模板数组.例如这段代码:
Guillaume Racicot gave an excellent answer to this question on how I could specialize template variables. But I'm having trouble in visual-studio-2017 with creating a templated array of function pointers. This code for example:
struct vec
{
double x;
double y;
double z;
};
namespace details
{
template <typename T>
constexpr double X(const T& param) { return param.x; }
template <typename T>
constexpr double Y(const T& param) { return param.y; }
template <typename T>
constexpr double Z(const T& param) { return param.z; }
}
template <typename T, typename = void>
constexpr double (*my_temp[])(const vec&) = { &details::X<T>, &details::Y<T> };
template <typename T>
constexpr double (*my_temp<T, enable_if_t<is_floating_point_v<decltype(details::X(T()))>>>[])(const vec&) = { &details::X<T>, &details::Y<T>, &details::Z<T> };
int main() {
vec foo = { 1.0, 2.0, 3.0 };
for(const auto i : my_temp<decltype(foo)>) {
cout << (*i)(foo) << endl;
}
}
在 gcc 输出中:
1
2
3
1
2
3
但是在 visual-studio-2017 仅输出:
1
2
我可以做些什么来解决这个问题吗?
Is there something I can do to work around this?
推荐答案
欢迎来到编译器错误的世界!您的语法完全有效,但只有 GCC 可以编译它.
Welcome to the world of compiler bugs! Your syntax is completely valid, yet only GCC can compile it.
到目前为止,我测试了多个 clang、gcc 和 msvc 版本.
So far, I tested with multiple clang, gcc and msvc versions.
您使用函数指针原始数组的变体,只有 GCC 可以正确解析它.Clang 8.0.0 会崩溃,MSCV 不会编译.
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.
我尝试了另外两种变体:使用模板别名和 std::array
I tried two other variations: with a template alias and std::array
函数指针别名模板:
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:
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>
};
要删除 CTAD,只需使用 std::array<auto(*)(const vec&) ->双倍,3>
.
To remove CTAD, simply use std::array<auto(*)(const vec&) -> double, 3>
.
结果如下:
+------------+-------+-------+-------+
| Compiling? | GCC | Clang | MSVC |
+------------+-------+-------+-------+
| raw array | Yes | ICE | No |
+------------+-------+-------+-------+
| fptr alias | Yes | ICE | Yes |
+------------+-------+-------+-------+
| std::array | Yes | Yes | Yes |
+------------+-------+-------+-------+
请注意,在即将发布的 clang 9 中,它将与 GCC 相提并论.所有版本至少需要 MSVC 2017.通过解决方法,我确信它也可以与 msvc 2015 一起使用.
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.
最后,只要它在您现在需要的平台上运行,就可以了.std::array
的编译时间成本很小,但到目前为止,原始数组的可移植性令人惊讶.
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.
相关文章