Свободные теоремы в C ++: являются ли шаблоны по своей природе невежественными и нейтральными по отношению к своим объектам неизвестных типов? - PullRequest
3 голосов
/ 30 июня 2019

Известно, что в Haskell, если у нас есть функция без конкретного типа, мы можем сделать вывод о ее поведении, например,

f : a -> a

всегда будет идентификатором.

С помощью Java Generics мыне может доказать, что универсальные функции имеют определенное поведение, поскольку мы можем использовать instanceof или методы базового класса Object для обхода ограничений, однако, если я вижу метод с сигнатурой

<T> List<T> reverse(List<T> list)

разумно предположить, что функция не будет использовать какие-либо свойства типа T.

Сигнатура типа шаблонной функции C ++, по-видимому, не дает никаких подсказок о ее реализации.Существует ли какая-либо функция, существующая или предлагаемая для стандарта, которая позволила бы нам писать сигнатуры функций, обеспечивающие аналогичные выводы в C ++?Например, какой-то способ сказать «Эта функция работает абсолютно для любого типа».

Ответы [ 4 ]

1 голос
/ 30 июня 2019

Нет, нет. Шаблоны очень специальные. По сути, это просто макросы, расширение которых определяется информацией о типе. Возможность создания шаблона с данным типом определяется почти полностью на основе расширения. Фактически, разрешается создавать экземпляр шаблона таким образом, чтобы только части его расширения могли проверять тип, если другие биты не используются.

Зависит ли проверка типа раскрытия от многих, многих идиосинкразий C ++, его синтаксиса и семантики. Из-за проблемных функций, таких как перегрузка, неявное приведение, приведение и специализация шаблона, нет надежды на свойство параметричности, которое даст вам свободные теоремы.

В некоторых комментариях упоминаются понятия. Однако концепции не изменяют это свойство - они позволяют явно противоречить конкретизации, но, как и прежде, отсутствие такого ограничения не означает, что оно работает для всего.

1 голос
/ 30 июня 2019

Шаблон не нормальная вещь.Он не может быть скомпилирован как один, так как C ++ не имеет (и, вероятно, никогда не будет) никакой значимой концепции шаблона в качестве интерфейса и статического контракта между вызывающей и вызываемой сторонами, как «прямое объявление» для функции.Представьте себе мир, в котором любая функция на самом деле является макросом (почти как ужасный стиль #define, но не настолько плохо себя ведет) и должна быть расширена для проверки типа.Это почти то, что шаблоны.

Это также то, что делает шаблоны настолько мощными!Шаблоны образуют полный язык Тьюринга, поскольку создание экземпляров шаблонов может произойти.Это ужасный язык, поэтому constexpr был изобретен, чтобы иметь чистый язык для рекурсивных выражений времени компиляции без рекурсивных шаблонов.

Вы можете рассуждать только в терминах создания шаблонов.«Подпись» ничего вам не говорит. Подобно чистому lisp-подобному макросам, шаблоны никогда не компилируются должным образом по отдельности, даже с «экспортным шаблоном» , который требует повторного запуска компилятора после компоновки.

Кстати, идеяинсинуация одного члена комитета по стандарту C ++, что «шаблон экспорта» был продан экспертам C ++ как отдельная компиляция для шаблонов, как если бы они были обычными не встроенными функциями, это обман;ни один эксперт C ++ никогда не верил этому.

0 голосов
/ 30 июня 2019

Это то, что концепции должны делать в C ++ 20. Конечно, все существующие шаблоны являются неограниченными (кроме как с помощью enable_if трюка или подобного), поэтому явное использование концепции Any может быть полезно для документирования намерения.

Тем не менее, C ++ в любом случае не имеет параметрического полиморфизма: нет единого способа манипулировать «значениями» совершенно произвольного типа, поскольку нет указателей на ссылки.) Даже написание T() делает нетривиальные предположения о типе. Таким образом, (черновая) стандартная библиотека C ++ 20 предоставляет такие понятия «общего значения», как Movable, которые практически полезны, но предоставляют меньше бесплатных теорем.

0 голосов
/ 30 июня 2019

Может быть, вы имеете в виду ограничения и понятия C ++ 20: https://en.cppreference.com/w/cpp/language/constraints:

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

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

Обратите внимание, что эта функция добавлена ​​в C ++ 20 и только частично поддерживается GCC.

...