Visual Studio 中的模板化函数指针数组
Templated Function Pointer Arrays in Visual Studio
Guillaume Racicot 对这个问题给出了一个很好的答案,即我如何专门化模板变量。但是我在visual-studio-2017中创建函数指针的模板化数组时遇到了麻烦。例如,此代码:
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 阿拉伯数字
3
但在 visual-studio-2017 中,只有输出:
1 阿拉伯数字
我可以做些什么来解决这个问题吗?
欢迎来到编译器错误的世界!您的语法是完全有效的,但只有 GCC 可以编译它。
到目前为止,我测试了多个clang,gcc和msvc版本。
函数指针原始数组的变体,只有 GCC 才能正确解析它。Clang 8.0.0 将崩溃,MSCV 不会编译它。
我尝试了另外两种变体:使用模板别名和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>
.
结果如下:
+------------+-------+-------+-------+
| 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一起使用。
最后,只要它在您现在需要的平台上工作,就可以了。 std::array
编译时间成本很小,但到目前为止,原始数组的可移植性令人惊讶地低。
相关文章:
- QMetaObject invokeMethod的基于函数指针的语法
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- c++r值引用应用于函数指针
- 模板函数指针和lambda
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 带有类的函数指针
- () 函子后面的括号,而不是函数指针?
- 全局作用域中函数指针的赋值
- 使用"Task"函数指针队列定义作业管理器
- 将成员函数指针作为参数传递给模板方法
- 如何创建对象函数指针C++映射?
- 匹配函数指针作为模板参数?
- 通过函数指针定义类范围之外的方法
- 存储在类中的函数指针
- C++从函数指针数组调用函数
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 整数键映射到头文件中的成员函数指针
- 从类成员函数到类 C 函数指针的转换
- 如何将内联匿名函数分配给C++函数指针
- 将字符缓冲区强制转换为函数指针