C++ Проверка условий в шаблонах и зачем нужно *= при использовании type traits

Всем привет! Я видел некоторый код с type traits, где вместо

template <typename T, typename enable_if_t<..something>>

Делают примерно так:

template <typename T, typename enable_if_t<..something>*=nullptr>

Или так:

template <typename T, typename = enable_if_t<..something>>

Чем отличаются все эти 3 записи?(надеюсь я в них не ошибся) И второй вопрос: как лучше всего делать проверки на различные условия(для типов) в шаблонах?


Ответы (1 шт):

Автор решения: HolyBlackCat

Есть два популярных способа:

  • typename = std::enable_if_t<??>

  • std::enable_if_t<??, std::nullptr_t> = nullptr

Второй способ лучше, по двум причинам:

  1. Нельзя отключить проверку, передав какой-то свой тип в этот шаблонный аргумент.

  2. Можно сделать несколько функций, которые будут отличаться только условием. Если сделать это с первым способом, то компилятор будет ругаться на переопределение функции.

У второго способа есть разные вариации: std::enable_if_t<??, int> = 0, std::enable_if_t<??> * = nullptr (что эквивалентно std::enable_if_t<??, void *> = nullptr), и т. п. Но они плохи тем, что позволяют сгенерировать несколько разных копий шаблона, передав туда разные шаблонные аргументы. А у std::nullptr_t возможное значение только одно, поэтому с ним так не сделать. (В С++20 для этих целей также подходит какой-нибудь пустой класс.)

→ Ссылка