Проверка подписи параметра шаблона

Мне нужно замаскировать некоторые ведущие бит значения. Если значение без знака, я могу утверждать (гарантировать), что какое-то произвольное количество старших бит не задано, то есть гарантированно ограниченное значение.

Если он подписан, мне нужно замаскировать ведущие биты (превращение значения в некоторую непереносимую кучу бит, да, я знаю об этом:-)). Я хотел бы сохранить операцию маскировки, если значение не указано.

Итак, у меня в основном есть

template<typename T, some more template parameters>
class {
    unsigned transform(T value) {
        ...
        if (isSigned(T)) {
            value &= mask;
        }
        ...
    }
}

Есть ли простой способ записи isSigned(), который можно оценить во время компиляции (чтобы оптимизатор мог удалить неподписанный мертвый код)?

Конечно, я мог бы добавить еще один параметр шаблона...

Ответы

Ответ 1

Да. Вы должны использовать частичную специализацию:

template <bool> struct impl { static void foo(); };
template <> struct impl<true> { static void foo(); };

template <typename T> struct Foo
{
    void do_magic(T const &)
    {
        impl<std::is_signed<T>::value>();
        // ...
    }
};

Вы можете использовать готовый класс is_signed от <type_traits> вместо того, чтобы кататься самостоятельно.

Ответ 2

if (T(-1) < T(0))

Но я бы поместил это в параметр шаблона и использовал его для специализации, а не для условного кода. Условный код, основанный на параметрах шаблона, часто приводит к ложным предупреждениям компилятора, таким как "недостижимый код" или "постоянное выражение в состоянии".

Что-то вроде:

template <typename T, bool is_signed>
inline void apply_mask_helper(T& value) { value &= mask; }

template <typename T>
inline void apply_mask_helper<T, false>(T&) { }

template <typename T>
inline void apply_mask(T& value) { apply_mask_helper<T, T(-1) < T(0)>(value); }

Ответ 3

Используйте numeric_limits из заголовка limits:

if(numeric_limits<T>::is_signed) { … }

Как сказал Керрек, Id идет с частичной специализацией. В противном случае компилятор может пожаловаться на то, что значение условия известно во время компиляции.