Как определить больший тип выражения decltype - PullRequest
5 голосов
/ 21 ноября 2011

Предположим, у меня есть такая функция:

static const boost::int32_t SOME_CONST_VALUE = 1073741823;
template<typename targetType, typename sourceType>
targetType Convert(sourceType source)
{
    typedef decltype(source * SOME_CONST_VALUE) MulType_t;
    //typedef boost::int64_t MulType_t;
    MulType_t val = (MulType_t)source * (MulType_t)SOME_CONST_VALUE;
    return val / (MulType_t)SOME_CONST_VALUE;
}

Когда я вызываю эту функцию следующим образом

boost::int32_t i = std::numeric_limits<boost::int32_t>::max();
boost::int32_t k = Convert<boost::int32_t>(i);

k равно 1 из-за переполнения при умножении. Приведение всего к boost::int64_t приведет к желаемому результату. Но я не хочу приводить short или char к значению int64.
Поэтому я могу использовать decltype, чтобы получить следующий больший тип выражения.

Ответы [ 2 ]

7 голосов
/ 21 ноября 2011

Вы должны сделать свою собственную специализацию шаблона для этого:

template<typename tp>
class bigger { }

template
class bigger<boost::int8_t>
{
    typedef boost::int16_t type;
}

template
class bigger<boost::int16_t>
{
    typedef boost::int32_t type;
}

template
class bigger<boost::int32_t>
{
    typedef boost::int64_t type;
}

Вы также можете создать макрос, если вам не нравится печатать много:

#define BIGGER(x, y) \
    template \
    class bigger<boost::int##x##_t> \
    { \
        typedef boost::int##y##_t type; \
    }

BIGGER(8, 16);
BIGGER(16, 32);
BIGGER(32, 64);

изатем используйте его как

bigger<boost::int32_t>::type x;
6 голосов
/ 22 ноября 2011

Ответ Дани имеет правильную идею, но заново изобретает колесо.
Boost.Integer был создан для решения проблемы выбора целочисленного типа .

static const boost::int32_t SOME_CONST_VALUE = 1073741823;
template<typename targetType, typename sourceType>
targetType Convert(sourceType source)
{
    typedef typename boost::int_t< 8 * sizeof( sourceType ) + 1 >::fast MulType_t;
    MulType_t val = static_cast<MulType_t>(source) * static_cast<MulType_t>(SOME_CONST_VALUE);
    return val / static_cast<MulType_t>(SOME_CONST_VALUE);
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...