2016-10-25 2 views
0

Я видел this вопрос здесь, но он не отвечает на то, что я имел в виду, в частности, подробно. Если такие языки, как Go или C++ 11, не используют алгоритм вывода, такой как Damas-Milner, что именно они делают? Я не думаю, что это так просто, как принимая тип на правой стороне, потому что, если вы что-то вроде:Как вывод типа реализован на языке C++ 11 или Go?

5 + 3.4 

Как бы компилятор расшифровать, какой тип, который? Есть ли какой-либо алгоритм, который не так прост, как

if left is integer and right is float: 
    return float; 
if left is float and right is integer: 
    return float; 
etc... for every possible pattern 

И если бы вы могли объяснить простые вещи, это было бы здорово. Я не изучаю конструкцию компилятора или любую из теоретических тем очень подробно, и я действительно не говорю на функциональных языках или сложной математической нотации.

+0

Это больше похоже на: * "если left целое, а справа - float, конвертируйте left to float и добавьте два поплавка" *. Преобразования выполняются (по мере необходимости) для каждого двоичного оператора в выражении, и результат заканчивается наивысшим ранжирующим типом в выражении. – user3386109

ответ

4

Я не думаю, что это так просто, как принимая тип на правой стороне

Для базового типа умозаключений формы auto var = some_expression;, это именно так просто. Каждое хорошо типизированное выражение имеет ровно один тип, и этот тип будет типом var. Не будет никакого неявного преобразования из типа выражения в другой тип (как может быть, если вы указали явный тип для var).

что, если у вас что-то вроде:

5 + 3.4 

вопрос "? Что такое тип 5 + 3.4" не является специфическим для вывода типа, компиляторы C++ всегда должны были ответить на этот вопрос - даже до ввода типа.

Итак, давайте сделаем шаг назад и посмотреть на то, как компилятор C++ typechecks в заявлении some_type var = some_expression;:

Сначала он определяет тип some_expression. Поэтому в коде вы можете себе представить что-то вроде Type exp_type = type_of(exp);. Теперь он проверяет, равен ли exp_typesome_type или существует неявное преобразование от exp_type до some_type. Если это так, оператор хорошо типизирован и var вводится в окружающую среду как имеющий тип some_type. Иначе это не так.

Теперь, когда мы вводим определение типа и писать auto var = some_expression;, изменения уравнение, как например: Мы до сих пор Type exp_type = type_of(exp);, но вместо того, чтобы затем сравнить его с другим типом или применения каких-либо неявные преобразования, мы вместо того, чтобы просто установить exp_type как тип var ,

Итак, давайте вернемся к 5 + 3.4. Каков его тип и как его определяет компилятор? В C++ его тип - double. Правила определения типа арифметического выражения перечислены в стандарте C++ (ищите «обычные арифметические преобразования», но в основном сводятся к следующему: из двух типов операндов выберите тот, который может представлять больший диапазон значений. Если тип меньше int, преобразуйте оба операнда в int. В противном случае преобразуйте оба операнда в выбранный вами тип.

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

Type type_of_binary_arithmetic_expression(Type lhs_type, Type rhs_type) { 
    int lhs_rank = conversion_rank(lhs_type); 
    int rhs_rank = conversion_rank(rhs_type); 
    if(lhs_rank < INT_RANK && rhs_rank < INT_RANK) return INT_TYPE; 
    else if(lhs_rank < rhs_rank) return rhs_type; 
    else return lhs_type; 
} 

Предположительно правила Go несколько отличаются, но те же самые принципы применимы.