В своём блоге Герб Саттер приводит примеры нескольких новых особенностей C++, которые вошли в черновой вариант стандарта C++09. Я решил сделать небольшой обзор наиболее интересных из них.
Начнём с шаблонных алиасов (Template aliases (aka typedef templates, generalized typedefs) [N2258]) . Данная возможность позволяет зафиксировать часть параметров шаблона.
// Не является правильным в C++, но хотелось бы...
//
template<typename T>
typedef std::map<std::string, T> Registry;
// Тогда можно было бы написать следующее:
//
Registry<employee> employeeRoster;
Registry<void(*)(int)> callbacks;
Registry<classfactory*> factories;
В C++09 вводится более обобщенная поддержка алиасов:
// Разрешено в C++09
//
template<typename T>
using Registry = std::map<std::string, T>;
// Теперь это работает, как и задумывалось:
//
Registry<Employee> employeeRoster;
Registry<void (*)(int)> callbacks;
Registry<ClassFactory*> factories;
Пока для создания подобного поведения можно использовать шаблонную стуктуру-обёртку (на примере смарт-указателя, инкапсулирующего класс Loki::SmartPtr, который использует несколько стратегий в качестве параметров шаблона):
template<typename T>
struct shared_ptr
{
typedef Loki::SmartPtr
<
T, // T может быть любым, остальные параметры фиксированы
RefCounted, NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T>
>
type;
};
shared_ptr<int>::type p; // пример использования, “::Type” - выглядит зловеще
Одной из основных причин (но и не только) для введения в новом стандарте шаблонных алиасов является удобство в использовании. Теперь при написании подобного кода не придётся явно указывать набор причудливых параметров, которые невозможно спрятать с помощью обычного алиаса:
// Разрешено в C++09
//
template<typename T>
using shared_ptr =
Loki::SmartPtr<
T,
RefCounted, NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T>
>;
shared_ptr<int> p; // вариант в C++09
Следует заметить, что применение новых алиасов не ограничивается только шаблонами:
// Верно в C++98 and C++09
//
typedef int Size;
typedef void (*handler_t)(int);
// Верно в C++09
//
using Size = int;
using handler_t = void (*)(int);
Для таких типов, как указатели на функции, это особенность новой формы "using" весьма важна, поскольку она является более простой в использовании и наглядной, чем typedef.
Продолжение следует...
Комментариев нет:
Отправить комментарий