Вы смотрите на это неправильно (хотя я не буду винить вас: сначала это довольно удивительно). Вам может показаться, что конструкторы следуют синтаксису Name of type
, где часть типа соответствует синтаксису обычного типа (что позволяет содержать кортежи).
В действительности кортежи и конструкторы следуют точно такому синтаксису: конструктор - это просто кортеж с именем перед ним:
tuple/constructor == [name of] type [* type] [* type] ...
Таким образом, *
в определении конструктора не являются частью синтаксиса кортежа, они являются частью синтаксиса конструктора. Вы буквально определяете конструктор как это имя, за которым следует N аргументов вместо этого имени, за которым следует аргумент, который является кортежем .
Причина этой тонкой разницы в поведении связана с производительностью. Прямо сейчас кортежи и конструкторы представлены в памяти так:
[TYPE] [POINTER] [POINTER] [POINTER]
Это довольно компактное и эффективное представление. Если множественные аргументы конструктора действительно могут быть доступны как кортеж, это потребует от среды выполнения представления этого кортежа независимо от конструктора (для того, чтобы он был независимо адресуемым), и поэтому он будет выглядеть следующим образом:
[TYPE] [POINTER]
|
v
[TYPE] [POINTER] [POINTER] [POINTER]
Это позволило бы использовать немного больше памяти, потребовать вдвое больше выделений при использовании конструктора и снизить производительность кортежей сопоставления с образцом (из-за дополнительной разыменования). Чтобы сохранить максимальную производительность, name of type * type
представлен с использованием первого шаблона, и вам нужно явно набрать name of (type * type)
, чтобы отрезать *
от of
и, таким образом, использовать второй шаблон.
Обратите внимание, что оба шаблона доступны через один и тот же синтаксис сопоставления и построения шаблонов: name (arg,arg)
. Это означает, что вывод типа не может вывести шаблон на основе использования. Это не проблема для обычных конструкторов, которые всегда определяются в определении типа, но это приводит к тому, что варианты (которые не нуждаются в предварительном определении) автоматически возвращаются к версии second .
Дополнительное чтение в памяти представления типов здесь .