变量模板中的除法 Returns 零 Visual Studio 2017

Division in Variable Template Returns Zero in Visual Studio 2017

这可能是 bug related to this question: And as 似乎与优化器有关。


一个variable template定义中的划分似乎在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;
}

On gcc 6.3 这输出:

0.0174533

2017 年 Visual Studio 输出:

0.0

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

我按原样测试了您的代码并得到了相同的结果。然而,我也单独测试了 PI & ONE_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.

的 LHS const T 变量之前进行除法运算

我不是 100% 确定,也不要在这方面引用我的话,但根据我自己的理解,我认为这可能是运算符优先顺序的问题。我认为在 visual studio 中没有将 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 种模式下都试过了:Debug/Release x86 和 x64,我得到了相同的结果。 这在您的机器平台上可能有所不同。

应@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