Читать «Эффективный и современный С++. 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
, а это означает, что ничто иное в этой области видимости не должно иметь такое же имя: