Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

шаблонный класс, не использующий аргумент шаблона

#cpp


Как понимать и как использовать шаблонный класс, например, такой?

template
    struct is_array
    : public false_type { };


P.S. Определен в   
    


Ответы

Ответ 1



Ваш пример, скорее всего, как раз таки НЕ является примером шаблона, "не использующего" свой аргумент. Вы привели лишь определение главного шаблона. А на самом деле за ним следовала еще одна или более специализаций этого шаблона. Так как выбор конкретной специализации делается на основе анализа аргумента, такой шаблон нельзя назвать "не использующим" свой аргумент. Аргумент в нем очень даже используется. Если вопрос вообще о шаблонных классах, действительно не использующих аргументы шаблона, то и у них есть свои предназначения. Не претендуя на полноту: Это способ генерации уникальных типов, не совпадающих ни с какими другими типами, а только с самими собой. Такие уникальные типы могут использоваться в качестве "тэговых" типов для специализации шаблонов и для перегрузки функций. Например, я могу завести шаблон "ранг", который внешне никак не зависит от своего параметра R template struct rank {}; Все, чего я хочу - это чтобы rank<0>, rank<1>, rank<2> и т.д. были самостоятельными типами. Затем я буду использовать этот шаблон в каких-то своих типах для назначения им "ранга" следующим образом struct MyType { using rank = ::rank<0>; ... }; struct MyOtherType { using rank = ::rank<3>; ... }; struct MyOtherOtherType { using rank = ::rank<0>; ... }; после этого для таких типов я смогу использовать перегрузку функций, чтобы обработка типа зависела от его ранга template void process(T& t, ::rank<0>) { // Обработка для ранга 0 } template void process(T& t, ::rank<1>) { // Обработка для ранга 1 } // И т.д. // Функция-диспетчер template void process(T& t) { process(t, typename T::rank()); } и потом MyType m; process(m); // В конечном итоге вызовется обработка для ранга 0 Именно эта техника используется уже давно при обработке итераторов на основе их категорий. Сам категории не являются шаблонами, но идея - та же. Сейчас, наверное, есть более элегантные методы реализации того же, но тем не менее. Это просто возможность предоставить пользователю место, где можно указывать аргументы чисто ради указания аргументов. "Указание аргументов чисто ради указания аргументов" используется, например, в SFINAE. Для этих целей, в частности, служит std::void_t (см. пример с https://en.cppreference.com/w/cpp/types/void_t) // primary template handles types that have no nested ::type member: template< class, class = std::void_t<> > struct has_type_member : std::false_type { }; // specialization recognizes types that do have a nested ::type member: template< class T > struct has_type_member> : std::true_type { }; В данном примере std::void_t служит только для того, чтобы нам было куда вписать typename T::type для целей SFINAE. Можно было обойтись и без std::void_t (и раньше мы без него обходились), но std::void_t унифицирует код, как бы подчеркивает тот факт, что это именно фиктивные аргументы для SFINAE. А также удобен тем, что в него можно вписывать сколько угодно аргументов. Это способ подогнать "сигнатуру" шаблона под какие-то жесткие внешние требования. Если нам нужен шаблон для передачи в качестве шаблонного аргумента в другой шаблон, то нам волей-неволей придется подгонять список параметров нашего шаблона-аргумента под требования параметра шаблона-получателя. Например, чтобы подготовить шаблон-аргумент для такого шаблонного класса template