6

I have a function but I want to split it into two functions, one for returning signed integers and one for unsigned integers. It looks like std::is_signed is not strictly for integers so I thought if I could a template test for something like std::is_integral<T>::value && std::is_signed<T>::value but that doesn't work. Right now I have the signed test as an if statement:

template<typename T>
typename std::enable_if
<
    std::is_integral<T>::value,
    T
>::type
foo()
{
    if( std::is_signed<T>::value )
    {
        //signed
    }
    else
    {
        //unsigned
    }
}


EDIT. I'm using Visual Studio 2010. Actually it looks like what's happening is Visual Studio will not accept two templates, one with std::is_integral<T>::value && std::is_signed<T>::value and one with std::is_integral<T>::value && std::is_unsigned<T>::value. It tells me function template has already been defined. Am I doing this wrong and is there a more standard compliant way to have two functions, one that is for returning unsigned integral, and one for signed integral?

PersianGulf
  • 2,845
  • 6
  • 47
  • 67
loop
  • 3,460
  • 5
  • 34
  • 57
  • I think what you want to do is partial function specialization, which is not supported. For example: one parameter T for the integral type and an additional bool parameter for signed/unsigned, which you specialize for. You'll have to implement them in a partially specialized class instead (or implement it as you did, which is probably equivalent performance-wise). – heinrichj Mar 24 '14 at 07:10
  • This question is now answered but this related question may also help anyone in the same situation: http://stackoverflow.com/q/9285657/894506 – loop Mar 25 '14 at 01:32

2 Answers2

3

Oops... just seen your edit... so you're trying to create alternative code... this work in the ideone demo here:

template <typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value,
                        int>::type f();


template <typename T>
typename std::enable_if<std::is_integral<T>::value && !std::is_signed<T>::value,
                        unsigned>::type f();
...

Do you want to give that a spin with VS2010 and report the outcome?

Alternatively, you could do this with std::conditional combines with the if statement you've got in your question's code - the unused code will be optimised away at compile time).

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Logical NOT `!` appears to be the correct answer but I think your example is wrong for the question and may confuse someone if I mark it correct. This worked: `std::is_integral::value && !std::is_signed::value`. If you amend your answer to reflect that specifically I will accept it. Your example is `!std::is_integral::value || !std::is_signed::value` which as far as I can tell seems to mean `not an integer type or if it is then not a signed arithmetic type` but as I said I needed separate functions for signed and unsigned integral types. – loop Mar 24 '14 at 18:11
3

I might use tag dispatching:

namespace Detail
{
    template <typename T>
    T fooHelper(std::true_type /*isSignedTag*/)
    {
        //signed
    }
    template <typename T>
    T fooHelper(std::false_type /*isSignedTag*/)
    {
        //unsigned
    }
}
template <typename T>
T foo()
{
    return Detail::fooHelper<T>(typename std::is_signed<T>::type());
}
Oktalist
  • 14,336
  • 3
  • 43
  • 63