Будет ли в стандартной библиотеке C ++ концепция арифметических типов?


person Adam Bucior    schedule 23.09.2019    source источник
comment
Похоже на недосмотр, поскольку существует std::is_arithmetic. Вы можете использовать это, чтобы написать свою собственную концепцию.   -  person NathanOliver    schedule 23.09.2019
comment
При таком способе мышления мы могли бы сказать, что нам не нужны никакие концепции, потому что большинство концепций, определенных в заголовке ‹concepts›, имеют свою интегральную версию в ‹type_traits›, а некоторые даже реализуются с их помощью. Но интегральная константа и понятие - это совершенно разные вещи, и интегральная константа не может использоваться как понятие в списке параметров шаблона.   -  person Adam Bucior    schedule 23.09.2019
comment
Кроме того, определение арифметической концепции с std::is_arithmetic_v вместо концепций std::integral и std:floating_point приведет к тому, что компилятор не будет рассматривать эти концепции как более ограниченные версии арифметической концепции. Это описано в справочнике по C ++.   -  person Adam Bucior    schedule 23.09.2019
comment
Извините за редактирование, это была ошибка. Что-то что-то, понятия должны иметь свое дело, что-то что-то.   -  person Barry    schedule 23.09.2019


Ответы (2)


Есть ли веская причина, по которой его там нет? Или есть предложения добавить?

Нет никаких предложений по его добавлению, но я ожидал бы увидеть комментарий NB, который просто предлагает template <typename T> concept arithmetic = std::is_arithmetic_v<T>; (который не гарантирует, что C ++ 20 будет иметь эту концепцию, просто то, что в минимум будет учтено).

Стандартные концепции библиотеки были добавлены предложением диапазонов и были обусловлены потребностями в алгоритмах для определенных концепций. integral появляется много раз, но я думаю, arithmetic никогда не появлялся, и поэтому его просто так и не добавили. Если вы посмотрите, скажем, на N4382 (с начала 2015 года), вы можете видеть, что IntegralSignedIntegral и UnsignedIntegral) были там с самого начала ... тогда как даже FloatingPoint был добавлен позже. (P0631, в июле 2019 ... и даже в статье, в которой добавлена ​​концепция с плавающей запятой, не упоминается arithmetic)


Конечно, тогда вы задаетесь забавным вопросом о том, должно ли оно быть основано исключительно на этой характеристике типа или должно быть template <typename T> concept arithmetic = integral<T> || floating_point<T>;, чтобы концепции integral и floating_point подпадали под arithmetic. Наверное? Может быть?

person Barry    schedule 23.09.2019

Отказ от ответственности: я не эксперт по C ++ и плохо знаком с концепциями C ++. Поэтому следующий ответ может немного сбить с толку, но я думал об этой концепции в другом контексте и думаю, что некоторые из пунктов здесь могут иметь отношение.

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

Интуитивно можно было ожидать, что концепция будет передавать следующее:

Рассматриваемый тип поддерживает основные арифметические операции +, -, * и /, и тип результата этих операций такой же, как и тип операндов. Судя по быстрому веб-поиску, эта идея формализована примерно так:

self operator+(self const& x, self const& y);
self operator−(self const& x, self const& y);
self operator∗(self const& x, self const& y);
self operator/(self const& x, self const& y);

Однако для правильной арифметики требуется еще кое-что:

  • должно быть закрытие элементов при данной операции
  • должен быть нейтральный элемент сложения (0)
  • должен быть нейтральный элемент умножения (1)
  • для каждого элемента должна быть добавочная инверсия (-x)
  • должен быть мультипликативный обратный для каждого элемента (/x - кроме нейтрального элемента сложения ...)

Вы видите, что здесь открыта банка с червями. Эти ограничения уже трудно или невозможно обеспечить для целочисленных типов, поскольку не может быть аддитивного обратного, особенно для unsigned типов. Для типов с плавающей запятой особые случаи быстро выходят из-под контроля из-за +/-inf и, что наиболее важно: NaN. Все это еще даже не учитывает ограниченную точность арифметики с плавающей запятой.


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


Так что концепция арифметики, которая выходит за рамки того, что это "либо float, либо int", безусловно, была бы интересной, но с множеством оговорок. Трудно сформулировать концепцию четко, чтобы ее можно было, например, также применить к комплексным числам или подобным структурам. И если кто-то попытался определить это, он, безусловно, также захотел бы охватить другие алгебраические структуры, такие как группы или кольца (например, для матриц или многочленов) или даже векторные пространства ...

По крайней мере, некоторые люди пробовали это: быстрый поиск в Интернете выявил Techcnical Report: Fundamental Algebraic Concepts in Concept-Enabled C ++, в котором рассматриваются некоторые из этих идей, включая арифметику, и указываются связанные с этим трудности. Однако это с 2006 года - могут быть новые исследования, основанные на концепциях, которые нашли свое отражение в стандарте.

person Marco13    schedule 24.09.2019
comment
Аддитивные инверсии для беззнаковых типов определены отлично, в отличие от таковых для подписанных типов. Требование мультипликативного обратного автоматически отбрасывает целочисленные типы (они в основном основаны на 2 ^ n, а FWIW Standard не указывает точные кардиналы). - person bipll; 04.07.2020
comment
@bipll Истинно, для обычных беззнаковых типов в C ++ аддитивная инверсия действительно определена (как в поведении not undefined) из-за (гарантированного) мода 2 ^ n- поведение, но только если указано n (как в uint32_t - это не относится к unsigned int). Любая попытка определить общую арифметику на беззнаковых целых числах может быть определена только на типах заданного размера, и хотя это возможно, оно, вероятно, будет иметь очень ограниченное применение, может показаться нелогичным и, конечно, нетривиальным для обобщения для других (нецелочисленных) типы. - person Marco13; 04.07.2020