Ответ 1
прежде всего, std:: common_type (и, конечно, boost:: type_traits:: common_type), используйте трёхмерный оператор для получения результата типа. В этом случае соответствующая цитата исходит из CppReference, 6b)
E2 и E3 имеют тип арифметики или перечисления: обычные арифметические преобразования применяются, чтобы привести их к общему типу, этот тип является результатом.
С помощью этой информации мы можем найти правила для обычных арифметических преобразований в стандарте С++, 5p10, стр. 88.
- В противном случае, если операнд с целым типом без знака имеет ранг, больший или равный рангам типа другого операнда, операнд со знаком целочисленного типа должен быть преобразован в тип операнда с целым числом без знака.
Итак, в основном ответ на ваш вопрос:... потому что стандарт говорит так.
Но вы не единственный, кто считает это поведение неожиданным. Вот пример быстрого запуска:
#include <iostream>
#include <typeinfo>
#include <type_traits>
int main(int argc, const char* argv[])
{
std::cout << typeid(std::common_type<char, unsigned char>::type).name() << std::endl;
// I would expect "short", and the result is "int", ok so far.
std::cout << typeid(std::common_type<short, unsigned short>::type).name() << std::endl;
// I would expect "int", and the result is "int", yay.
std::cout << typeid(std::common_type<int, unsigned int>::type).name() << std::endl;
// I would expect "long", but the result is "unsigned int"
std::cout << typeid(std::common_type<long, unsigned long>::type).name() << std::endl;
// I would expect "long long", but the result is "unsigned long"
// So this usual arithmetic conversion can lead to unexpected behavior:
auto var_auto = true ? var_i : var_ui;
std::cout << typeid(var_auto).name() << std::endl; // unsigned int
std::cout << var_auto << std::endl; // 4294967173
return 0;
}
Но проблема в том, что текущее поведение является проблемой и существует , чтобы удалить некоторые из сюрпризы.
-Hannes