Псевдонимы
С помощью объявления псевдонима можно объявлять имя, которое будет использоваться в качестве синонима к ранее объявленному типу. (В обычной речи такой механизм также называют псевдонимом типа.) С помощью этого механизма также можно создать шаблон псевдонима, который может быть особенно полезен для пользовательских механизмов выделения памяти.
using identifier = type;
Заметки
identifier
Имя псевдонима.type
Идентификатор типа, для которого создается псевдоним.
Псевдоним не вводит в программу новый тип и не может менять значение существующего имени типа.
В простейшей форме псевдонимы эквивалентны механизму typedef из версии языка C++03:
// C++11
using counter = long;
// C++03 equivalent:
// typedef long counter;
Оба этих механизма позволяют создавать переменные типа "счетчик". Псевдоним типа для std::ios_base::fmtflags, приведенный в следующем примере, может быть более полезен.
// C++11
using fmtfl = std::ios_base::fmtflags;
// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;
fmtfl fl_orig = std::cout.flags();
fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex;
// ...
std::cout.flags(fl_hex);
Псевдонимы также работают с указателями на функции, однако они обеспечивают большую удобочитаемость, чем их эквивалент typedef.
// C++11
using func = void(*)(int);
// C++03 equivalent:
// typedef void (*func)(int);
// func can be assigned to a function pointer value
void actual_function(int arg) { /* some code */ }
func fptr = &actual_function;
Механизм typedef имеет ограничение: он не работает с шаблонами. Напротив, синтаксис псевдонима типа в C ++11 позволяет создавать шаблоны псевдонимов:
template<typename T> using ptr = T*;
// the name 'ptr<T>' is now an alias for pointer to T
ptr<int> ptr_int;
Пример
В следующем примере показано, как использовать шаблон псевдонима с пользовательским механизмом выделения памяти — в данном случае целочисленным векторным типом. Любой тип можно заменить на int, чтобы создать удобный псевдоним для скрытия сложных списков параметров в основном коде функций. Применяя по всему коду пользовательские механизмы выделения памяти, можно повысить удобочитаемость и уменьшить риск возникновения ошибок, связанных с опечатками.
#include <stdlib.h>
#include <new>
template <typename T> struct MyAlloc {
typedef T value_type;
MyAlloc() { }
template <typename U> MyAlloc(const MyAlloc<U>&) { }
bool operator==(const MyAlloc&) const { return true; }
bool operator!=(const MyAlloc&) const { return false; }
T * allocate(const size_t n) const {
if (n == 0) {
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T)) {
throw std::bad_array_new_length();
}
void * const pv = malloc(n * sizeof(T));
if (!pv) {
throw std::bad_alloc();
}
return static_cast<T *>(pv);
}
void deallocate(T * const p, size_t) const {
free(p);
}
};
#include <vector>
using MyIntVector = std::vector<int, MyAlloc<int>>;
#include <iostream>
int main ()
{
MyIntVector foov = { 1701, 1764, 1664 };
for (auto a: foov) std::cout << a << " ";
std::cout << "\n";
return 0;
}