Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 51

Скотт Мейерс

В любом случае я не стремлюсь обеспечить вас учебником по свойствам типов. Вместо этого я прошу вас обратить внимание на то, что каждое преобразование завершается “::type”. Если вы применяете их к параметру типа в шаблоне (что практически всегда является их применением в реальном коде), то вы также должны предварять каждое их применение ключевым словом typename. Причина обоих этих синтаксических требований заключается в том, что свойства типов в C++11 реализованы как вложенные typedef внутри шаблонных структур struct. Да, это так — они реализованы с помощью технологии, о которой я говорю, что она уступает шаблонам псевдонимов!

Тому есть исторические причины, но здесь мы их опустим (честное слово, это слишком скучно), поскольку Комитет по стандартизации с опозданием признал, что шаблоны псевдонимов оказываются лучшим способом реализации, и соответствующие шаблоны включены в С++14 для всех преобразований типов C++11. Псевдонимы имеют общий вид: для каждого преобразования C++11 std::преобразование<T>::type имеется соответствующий шаблон псевдонима С++ 14 с именем std::преобразование_t. Вот примеры, поясняющие, что я имею в виду:

std::remove_const<T>::type         // C++11: const T -> T

std::remove_const_t<T>             // Эквивалент в С++14

std::remove_reference<T>::type     // C++11: T&/Т&& -> T

std::remove_reference_t<T>         // Эквивалент в С++14

std::add_lvalue_reference<T>::type // C++11: T -> T&

std::add_lvalue_reference_t<T>     // Эквивалент в С++14

Конструкции С++11 остаются в силе в С++14, но я не знаю, зачем вам может захотеться их использовать. Даже если у вас нет компилятора С++ 14, написание таких шаблонов псевдонимов самостоятельно — детская игра. Требуются только языковые возможности С++11, и даже ребенок сможет написать такие шаблоны. Если у вас есть доступ к электронной копии стандарта С++14, то все становится еще проще — вы можете просто скопировать необходимый код оттуда и вставить в свою программу. Вот вам для начала:

template <class T>

using remove_const_t = typename remove_const<T>::type;

template <class T>

using remove_reference_t = typename remove_reference<T>::type;

template <class T>

using add_lvalue_reference_t =

typename add_lvalue_reference<T>::type;

Судите сами — что может быть проще?

Следует запомнить

• В отличие от объявлений псевдонимов, typedef не поддерживает шаблонизацию.

• Шаблоны псевдонимов не требуют суффикса “::type”, а в шаблонах — префикса typename, часто требуемого при обращении к typedef.

• С++14 предлагает шаблоны псевдонимов для всех преобразований свойств типов C++11.

3.4. Предпочитайте перечисления с областью видимости перечислениям без таковой

В качестве общего правила объявление имени в фигурных скобках ограничивает видимость этого имени областью видимости, определяемой этими скобками. Но не так обстоит дело с перечислениями в С++98. Имена в таких перечислениях принадлежат области видимости, содержащей enum, а это означает, что ничто иное в этой области видимости не должно иметь такое же имя: