变量模板中的除法在 Visual Studio 2017 中返回零

Division in Variable Template Returns Zero in Visual Studio 2017

本文关键字:2017 Studio 返回 Visual 除法 变量      更新时间:2023-10-16

这可能是与此问题相关的visual-studio-2017错误:Visual Studio 中 Lambda 的模板化变量错误?正如评论中提到的,似乎与优化器有关。


变量模板定义的划分似乎在Visual Studio 2017中存在错误。所以这个代码例如:

template <typename T>
const T PI = std::acos(static_cast<T>(-1));
template <typename T>
const T ONE_EIGHTY = 180;
template <typename T>
const T DEG_TO_RAD = PI<T> / ONE_EIGHTY<T>;
int main() {
cout << DEG_TO_RAD<float> << endl;
}

在 gcc 6.3 上,输出:

0.0174533

在Visual Studio 2017上,此输出:

0,0

我假设这是另一个Visual Studio错误?这里有解决方法吗?

应@JonathanMee的要求在此处发布解决方法,因为它也适用于他之前报告的类似问题。似乎与最新VS2017中的某种错误有关,该错误阻止模板自动激活并需要强制激活:

template <typename T>
const T PI = std::acos(static_cast<T>(-1));
template <typename T>
const T ONE_EIGHTY = 180;
template <typename T>
const T DEG_TO_RAD = PI<T> / ONE_EIGHTY<T>;
int main() 
{
PI<float>; // <---- workaround
std::cout << DEG_TO_RAD<float> << std::endl;
}

这是向Microsoft提交的错误票:https://developercommunity.visualstudio.com/content/problem/207741/template-needs-to-be-force-instantiated-vs2017-bug.html

我按原样测试了您的代码并得到了相同的结果。但是,我也单独测试了PIONE_EIGHTY,他们在输出中给了我正确的结果。所以我考虑过它,出于某种原因,因为我不知道为什么Visual Studio这样做,这导致我认为它可能是一个错误,或者它可以留给compiler-implementation-design但似乎它没有设置两个预定义常量的划分const T DEG_RAD

要在Visual Studio中解决此问题,它非常简单且容易被忽略;您所要做的就是用括号包装RHS表达式。

template<typename T>
const T DEG_TO_RAD = (PI<T> / ONE_EIGHT<T>);

这不会打印出正确的值,因为它会在将值分配给声明为DEG_TO_RAD的 LHSconst T变量之前进行除法。

我不是 100% 确定,也没有引用我的话,但根据我自己的理解,我认为这可能是运算符优先级顺序的问题。我认为在视觉工作室中没有将 RHS 包装在括号中,它没有正确执行除法操作,因此DEG_TO_RAD设置为 0。

编辑

这是我的完整代码:当我尝试在堆栈上解决要回答的问题时,我将大约 80% 的标准库用于我的特定解决方案,所以我不会列出所有包含,但我确实拥有大多数容器、I/O、数字、算法、内存、函数、计时、cmath、GLM 等。

在 Win 7 上使用 Visual Studio 2017 v15.4.4 - 在英特尔四核至尊版上使用 64 位家庭高级版。

template <typename T>
const T PI = std::acos( static_cast<T>(-1) );
template <typename T>
const T ONE_EIGHTY = 180;
template <typename T>
const T DEG_TO_RAD = PI<T> / ONE_EIGHTY<T>; 
int main() {
std::cout << PI<float> << std::endl;
std::cout << ONE_EIGHTY<float> std::endl;
std::cout << DEG_TO_RAD<float> std::endl;
_getch(); // include <conio.h> // just to stop the debugger from auto close
return 0;
}

输出:

3.14159
180
0

然后当我这样做时:

template <typename T>
const T PI = std::acos( static_cast<T>(-1) );
template <typename T>
const T ONE_EIGHTY = 180;
template <typename T>
const T DEG_TO_RAD = (PI<T> / ONE_EIGHTY<T>); 
int main() {
std::cout << PI<float> << std::endl;
std::cout << ONE_EIGHTY<float> std::endl;
std::cout << DEG_TO_RAD<float> std::endl;
_getch(); // include <conio.h> // just to stop the debugger from auto close
return 0;
}

输出:

3.14159
180
0.0174533

我在所有 4 种模式下都尝试过这个:调试/发布 x86 和 x64,我得到了相同的结果。 这在您的计算机 - 平台上可能有所不同。