Division in Variable Template Returns Zero in Visu

2019-07-01 11:04发布

This is probably a 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?

2条回答
男人必须洒脱
2楼-- · 2019-07-01 11:44

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.

查看更多
老娘就宠你
3楼-- · 2019-07-01 12:00

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

查看更多
登录 后发表回答