Как изменить подпись имени типа в функции шаблона c++


Итак, я пытался сделать" циклический " побитовый сдвиг в c++ (11), и у меня есть базовый код, который сводится к следующему:

#include <cstdio>
#include <limits> // is_signed
#include <limits.h> // CHAR_BIT

template<typename T>
T rotl(T input, unsigned int shift)
{
    return (input<<shift)|(input>>(sizeof(T)*CHAR_BIT-shift));
}

template<typename T>
T rotr(T input, unsigned int shift)
{
    return (input>>shift)|(input<<(sizeof(T)*CHAR_BIT-shift));
}

int main()
{
    int i = -5;

    std::printf( "%in", i);

    i = rotl(i, 4); // or other value
    std::printf( "%in", i);

    i = rotr(i, 4); // same value as above
    std::printf( "%in", i);
}

Это дает мне ожидаемое поведение, когда выходные данные выглядят следующим образом:

-5
-1
-1

Поскольку int i подписан, однако если я сделаю это с кодом:

i = (int)rotl((unsigned int)i, 4);
. . .
i = (int)rotr((unsigned int)i, 4);

Выход становится:

-5
-65
-5

Который работает так, как я тоже хочу. Я также могу проверить подписанность T, используя numeric_limits следующим образом:

T rotr(T input, unsigned int shift)
{
    if(std::numeric_limits<T>::is_signed == false){
        return ()
    }else{
        return // problem here
    }
}
Но я, кажется, не могу понять, как это сделать. чтобы развернуться подпись-ности Т (unsigned T) является недопустимым для имен типов. Так как же мне это сделать? Я бы предпочел не использовать ничего, кроме стандартных библиотек (личный вкус действительно), но если нет никакого правдоподобного способа сделать это, я мог бы рассмотреть варианты без std.
1 2

1 ответ:

Как кельтский менестрель предложил использовать std::make_unsigned<T>::type

Вот как:


template&lttypename T&gt
T rotl(T input, unsigned int shift)
{
    typename std::make_unsigned&ltT&gt::type ii = static_cast&lttypename std::make_unsigned&ltT&gt::type&gt(input); 
    return static_cast&ltT&gt((ii<<shift)|(ii>>(sizeof(T)*CHAR_BIT-shift)));
}