Visual Studio中的模板化函数指针数组 [英] Templated Function Pointer Arrays in Visual Studio

查看:96
本文介绍了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

但是在仅输出:

1
2

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&) -> double, 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保持一致.所有版本都至少需要MSVC2017.通过变通办法,我相信也可以使其与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.

这篇关于Visual Studio中的模板化函数指针数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆