12

Какова разница между 'typedef' и 'using'?

15

Я знаю, что в C++11 мы можем использовать ключевое слово using для написания псевдонимов типов, аналогично typedef. Например:

typedef int MyInt;

Что, как я понимаю, эквивалентно:

using MyInt = int;

Эта новая синтаксическая конструкция появилась в рамках попытки создать способ для выражения "псевдонимов типов через шаблоны":

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

Однако, в случае с первыми двумя примерами (без шаблонов) есть ли какие-то другие тонкие различия в стандарте? Например, typedef создает псевдонимы "слабым" образом. Это значит, что он не создает новый тип, а только новое имя (преобразования между этими именами являются неявными).

Так ли это с using или он генерирует новый тип? Есть ли какие-либо различия между ними?

5 ответ(ов)

7

Они эквивалентны, согласно стандарту (выделение мое) (7.1.3.2):

Идентификатор (typedef-name) также может быть введен с помощью объявления-алиаса. Идентификатор, следующий за ключевым словом using, становится именем типа (typedef-name), а необязательная последовательность спецификаторов атрибутов (attribute-specifier-seq), следующая за идентификатором, относится к этому имену типа. У него те же семантические свойства, как если бы он был введен с помощью спецификатора typedef. В частности, он не определяет новый тип и не должен появляться в type-id.

4

Они в основном одинаковы, за исключением следующих моментов:

Объявление псевдонима совместимо с шаблонами, в то время как типовая запись в стиле C не совместима.

2

Синтаксис using имеет преимущества при использовании в шаблонах. Если вам нужна абстракция типа, но вы также хотите оставить возможность указать параметр шаблона в будущем, вам следует написать что-то вроде следующего.

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // чтобы в будущем можно было заменить whatever.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

Однако синтаксис using упрощает этот случай использования.

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }
0

Оба ключевых слова эквивалентны, но есть несколько нюансов. Во-первых, объявление указателя на функцию с помощью using T = int (*)(int, int); более ясно, чем с использованием typedef int (*T)(int, int);. Во-вторых, форма алиаса шаблона невозможна с typedef. В-третьих, при экспортировании C API потребуется использовать typedef в публичных заголовках.

0

using и typedef по сути выполняют одну и ту же функцию, но using предоставляет возможность создавать alias templates, что может быть весьма полезно. Пример, который хорошо иллюстрирует это, следующий:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

Таким образом, вместо того чтобы писать typename std::add_const<T>::type, мы можем просто использовать std::add_const_t<T>. Это делает код более читаемым и удобным.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь