typedef int Int
- это ужасная идея ... люди будут удивляться, смотрят ли они на C ++, это сложно набирать, визуально отвлекает, и единственное смутное объяснение для этого является ошибочным, но давайте поместим это явно, чтобы мы могли сбить его с ног:
если в один прекрасный день говорят, что 32-битное приложение портировано на 64-битное, и существует множество глупых кодов, которые работают только для 32-битных целых, то по крайней мере typedef можно изменить на держать Int на 32 бита.
Критика: если система засорена тем кодом, который написан так плохо (т.е. не использует явно 32-битный тип из cstdint), в подавляющем большинстве случаев могут быть другие части кода, где теперь нужно будет использовать 64- Битовые биты, которые застрянут в 32-битной версии через typedef. Код, взаимодействующий с библиотечными / системными API-интерфейсами с использованием целочисленных значений, скорее всего получит целочисленные значения, что приведет к усеченным дескрипторам, работающим до тех пор, пока они не окажутся за пределами 32-битного диапазона и т. Д. Код должен быть полностью пересмотрен, прежде чем в любом случае будет заслуживающим доверия. Наличие такого обоснования в сознании людей может только отговорить их от использования типов явно заданного размера, где они действительно полезны («для чего вы это делаете?», «Переносимость?», «Но Int для переносимости, просто используйте это»).
Тем не менее, правила кодирования могут быть предназначены для поощрения typedef для вещей, которые являются логически различными типами, такими как температура, цены, скорости, расстояния и т. Д. В этом случае typedefs могут быть весьма полезны, поскольку они позволяют легко способ перекомпилировать программу, скажем, обновить с float
точность до double
, понизить с реального типа на цельный или заменить пользовательский тип некоторыми специальными поведениями. Это также очень удобно для контейнеров, так что при изменении контейнера будет меньше работы и меньше влияния на клиента, хотя такие изменения, как правило, немного болезненны: API-интерфейсы контейнера разработаны так, чтобы быть немного несовместимыми, поэтому важные части должны быть пересмотрены вместо того, чтобы компилировать, но не работать или молча выполнять намного хуже, чем раньше.
Важно помнить, что typedef
является только «псевдонимом» фактического базового типа и фактически не создает новый отдельный тип, поэтому люди могут передавать любое значение того же типа, не получая никакого вида. предупреждения компилятора о несоответствии типов. Это можно обойти с помощью шаблона, например:
template <typename T, int N>
struct Distinct
{
Distinct(const T& t) : t_(t) { }
operator T&() { return t_; }
operator const T&() const { return t_; }
T t_;
};
typedef Distinct<float, 42> Speed;
Но трудно сделать значения N уникальными ... возможно, вы можете иметь центральный enum
, перечисляющий различные значения, или использовать __LINE__
, если вы имеете дело с одной единицей перевода и без нескольких typedefs на линии, или возьмите const char*
из __FILE__
, но я не знаю особо элегантного решения.
(Одна классическая статья 10 или 15 лет назад продемонстрировала, как можно создавать шаблоны для типов, которые знают несколько ортогональных единиц, сохраняя счетчики текущей «мощности» в каждой и настраивая тип по мере выполнения умножений, делений и т. Д. Например, вы можете объявить что-то вроде Meters m; Time t; Acceleration a = m / t / t;
и проверить, все ли единицы были разумны во время компиляции.)
Это хорошая идея? Большинство людей явно считают это излишним, поскольку почти никто никогда не делает это. Тем не менее, это может быть полезно, и я использовал его несколько раз, когда было легко и / или особенно опасно, если значения были случайно ошибочно назначены.