2015-06-04 2 views
1

Я попытался следующие:Когда я использую typedef или использую для int, сколько это еще int?

using Idx = int; 
array<Value, N> arr; 

for(Idx i = 0; i < N; i ++){ 
    arr[i].doSomething(); 
} 

Я ожидал, что компилятор будет выдавать предупреждение или сообщение об ошибке при попытке использовать Idx, как если бы это был int. Но это не так.

Итак, когда я использую using или typedef для псевдонима типа A в качестве B, являются ли переменными типа B еще и типа A, и наоборот? Таким образом, безопасность типа не может быть достигнута путем переименования типа, когда он выглядит одинаково, но имеет другое значение.

(Это связано со следующим вопросом я недавно спросил: How to make types for indexing)

+3

Ключевое слово здесь - это слово [* "alias" *] (http://en.wiktionary.org/wiki/alias), что означает 'Idx' (в вашем случае) - просто другое имя для' int'. –

+1

Еще 100% int – user763305

ответ

3

Декларация псевдонима или typedef просто делает новое имя для совмещенного типа. Idx не отличается от int в этом случае; они могут использоваться взаимозаменяемо без разницы в семантике.

Из [dcl.typedef] (курсив мой):

Имя объявляется с спецификатором ЬурейиМ становится именем-ЬурейиМ. В пределах своего объявления имя typedef синтаксически эквивалентно ключевому слову и называет тип, связанный с идентификатором, в способом, описанным в разделе 8. Таким образом, typedef-name является синонимом другого типа. В typedef-name не вводится новый тип, как это делает объявление класса или объявление перечисления.

1

typedef и эквивалентные using заявления не добавляют типобезопасность в том, что они представляют альтернативные идентификаторы для же типа.

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

template <typename T, size_t Id> 
struct Distinct_Type 
{ 
    explicit Distinct_Type(const T& t) : t_(t) { } 
    const T& get() const { return t_; } 
    ...whatever else... 
    T t_; 
}; 

А использование как:

typedef Distinct_Type<int, __LINE__> Age; 
void f(Age); 
void g() { f(Age(88)); /*forced explicit construction*/ } 

Ясно __LINE__ противная и подвержен ошибкам хак : с C++ 11 можно создавать добавочные значения времени компиляции, которые работают надежно, но код слишком длинный для отдыха и включения здесь - google, если это интересно.

Эти действительно-различные типы имеют проблемы, хотя, например, если вы вызываете функцию как template <typename T> void f(T t); ала f(Distinct_Type<int, 1>(1));, f(Distinct_Type<int, 2>(1));, f(Distinct_Type<int, 3>(1)); - компилятор/линкер может или не может устранить два из трех конкретизации из исполняемого образа, уменьшая раздувание кода.

1

Было бы неплохо иметь простой способ получения классов из встроенных типов, особенно если автоматические преобразования были отключены. Например, можно определить различные целые классы для ног и метров, предотвращая ошибки, подобные тем, которые привели к Mars Orbiter Crash in 1999. Ада с упором на безопасность provides that feature. Причина, по которой это невозможно в C++, приведена в another answer (ОП пыталась явно наследовать от int): система типа C для ints настолько «хаотична» (Stroustrup), что делает эти типы непригодными для построения блоков в иерархии классов.

Как и на C++, необходимо написать оболочку, включающую все операции, которые требуется иметь, которые автоматически предоставляются в случае Ada.