Home Dashboard Directory Help
Search

std::numeric_limits<T>::is_signed generates warning in function template compiled Release by Steve Huston


Status: 

Closed
 as By Design Help for as By Design


1
0
Sign in
to vote
Type: Bug
ID: 777327
Opened: 1/23/2013 4:18:12 PM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

In all of Visual Studio 2012, 2010 and 2008 I experience this problem. The following code compiles and runs correctly when compiled in Debug mode. When compiled in Release mode it runs correctly but generates a compile warning. Our project's guidelines do not allow code with warnings to be used.

#include <limits>
#include <iostream>

typedef unsigned int     uint32_t;
typedef int             int32_t;
typedef unsigned __int64 uint64_t;

template<class T> T convert()
{
T r = 4;
if (std::numeric_limits<T>::is_signed) {
    return -r;                    
} else {
    if (r==0) return 0;
}
return r;
}

int main(int, char *[])
{
std::cout << "unsigned int: " << std::numeric_limits<unsigned int>::is_signed << std::endl;
std::cout << "uint32_t: " << std::numeric_limits<uint32_t>::is_signed << std::endl;
std::cout << "unsigned __int64: " << std::numeric_limits<unsigned __int64>::is_signed << std::endl;
std::cout << "uint64_t: " << std::numeric_limits<uint64_t>::is_signed << std::endl;

std::cout << "uint32_t 4 is " << convert<uint32_t>() << std::endl;
std::cout << "int32_t 4 is " << convert<int32_t>() << std::endl;

return 0;
}
Details
Sign in to post a comment.
Posted by Microsoft on 2/6/2013 at 7:57 PM
Hi,

Thanks for reporting this issue. I've resolved it as By Design because the compiler and Standard Library implementation are working correctly here.

When you instantiate convert<uint32_t>(), the compiler sees a test that will be executed at runtime, followed by unary minus being applied to an unsigned integer. Although it warns that the conditional expression is constant (at /W4), it also warns about the unary minus, despite the fact that that code will never be executed at runtime.

If you want your code to compile cleanly without suppressing warnings, you need to perform this test at compiletime. There are many ways to do so, but the easiest way (which we prefer in the STL's implementation) is "tag dispatch":

C:\Temp>type meow.cpp
#include <stdint.h>
#include <iostream>
#include <type_traits>
using namespace std;

template <typename T> T convert_helper(T t, true_type) {
    return -t;
}

template <typename T> T convert_helper(T t, false_type) {
    return t;
}

template <typename T> T convert() {
    T t = 4;

    return convert_helper(t, is_signed<T>());
}

int main() {
    cout << "convert<int32_t>(): " << convert<int32_t>() << endl;
    cout << "convert<uint32_t>(): " << convert<uint32_t>() << endl;
}

C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp
meow.cpp

C:\Temp>meow
convert<int32_t>(): -4
convert<uint32_t>(): 4

What's happening here is that is_signed<T> is a struct template that derives from either a true_type struct or false_type struct (in reality they are typedefs, but thinking of them as plain old structs is correct here). In my example, convert() says is_signed<T>() to construct a temporary object of this type. I could also have said is_signed<T> dummy; followed by return convert_helper(t, dummy); although that would be more verbose. Overload resolution then selects either convert_helper(T, true_type) or convert_helper(T, false_type). (We are passing an object of derived type by value. Doing this "slices" it, but we don't care - we're doing this for overload resolution only, and we don't care about the dummy object itself. convert_helper() doesn't even bother to name this parameter.) The key part is that only the desired overload of convert_helper() is instantiated. For unsigned types, the expression "-t" is never compiled, because that's in an overload that isn't selected.

Note: Connect doesn't notify me about comments. If you have any further questions, please E-mail me.

Stephan T. Lavavej
Senior Developer - Visual C++ Libraries
stl@microsoft.com
Posted by Microsoft on 1/23/2013 at 10:20 PM
Thank you for submitting feedback on Visual Studio and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by Microsoft on 1/23/2013 at 4:50 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
File Name Submitted By Submitted On File Size  
test.cpp 1/23/2013 899 bytes