问题描述
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;
}
}
但是在视觉- studio-2017 仅输出:
有什么办法可以解决这个问题?
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:
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中的模板化函数指针数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!