Division in Variable Template Returns Zero in Visual Studio 2017

断了今生、忘了曾经 提交于 2019-12-14 01:29:01

问题


This is probably a visual-studio-2017 bug related to this question: Templated Variables Bug With Lambdas in Visual Studio? And as mentioned in the comments there seems to be optimizer related.


Division in the definition of a variable template seems to have a bug in Visual Studio 2017. So this code for example:

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 this outputs:

0.0174533

On Visual Studio 2017 this outputs:

0.0

I'm assuming this is another Visual Studio bug? Is there a workaround here?


回答1:


Posting a workaround here at the request of @JonathanMee as it also works for the similar problem reported by him earlier. Seems to be connected with some sort of bug in latest VS2017 that prevents template from activating automatically and needs a force activation:

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;
}

Here is a bug ticket filed with Microsoft: https://developercommunity.visualstudio.com/content/problem/207741/template-needs-to-be-force-instantiated-vs2017-bug.html




回答2:


I tested your code as is and got the same results. However I also tested PI & ONE_EIGHTY individually and they were giving me the correct results in the output. So I had thought about it, and for some reason as I don't know why Visual Studio is doing this which leads me to think that it could be a bug or that it could be left to the compiler-implementation-design but it appears that it is not setting the const T DEG_RAD from the division of the two predefined constants.

To fix this problem in visual studio it is quite simple and easily over looked; all you have to do is wrap the RHS expression with parenthesis.

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

And this will not print out the correct values as it will do the division before assigning the value to the LHS const T variable declared as DEG_TO_RAD.

I'm not 100% certain and don't quote me on this, but from my own understanding I think this could be an issue of operator precedence order. I think in visual studio without wrapping the RHS in parenthesis it is not performing the operation of division properly thus DEG_TO_RAD is being set to 0.

EDIT

Here is my full code: I am using about 80% of the standard library for my particular solution for when I try to work out problems to answer here on stack so I will not list all of the includes but I do have most all containers, I/O, numeric, algorithms, memory, functional, chrono, cmath, GLM etc.

Using Visual Studio 2017 v15.4.4 on Win 7 - 64bit Home Premium on a Intel Quad Core Extreme.

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;
}

Output:

3.14159
180
0

Then when I do this:

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;
}

Output:

3.14159
180
0.0174533

I tried this in all 4 modes: Debug/Release x86 & x64 and I get the same results. This may be different on your machine - platform.



来源:https://stackoverflow.com/questions/49118587/division-in-variable-template-returns-zero-in-visual-studio-2017

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!