четверг, 24 мая 2007 г.

C++09 - новый стандарт, новые возможности

В своём блоге Герб Саттер приводит примеры нескольких новых особенностей 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.

Продолжение следует...

Комментариев нет: