Роль аргументов шаблона по умолчанию в контексте частичной специализации - PullRequest
0 голосов
/ 01 октября 2018

Мне не ясно, как взаимодействуют аргументы шаблона по умолчанию в контексте частичной специализации, для выбора которой лучше всего подходит шаблон.Этот вопрос проистекает из кода, опубликованного в этом ответе по max66.

С учетом определений классов A и B:

template <int N> struct A { static const int code = N; };

struct B{};

и следующихклассы шаблонов:

// primary template
template <typename, typename Enable = bool_constant<true>>
struct cond : public bool_constant<false> {};

// specialization
template <typename T>
struct cond<T, bool_constant<(0 == T::code)>> : public bool_constant<true> {};

1) cond<B>::value оценивается как false (т.е. выбран основной).Это ясно, поскольку первичный шаблон дает cond<B, bool_constant<true>>, специализация терпит неудачу, следовательно, первичный шаблон является единственным возможным выбором.

2) cond<A<0>>::value оценивается как true (т.е. специализация выбрана).Это ясно, поскольку первичный шаблон дает cond<B, bool_constant<true>>, специализация также дает cond<B, bool_constant<true>>, поэтому специализация предпочтительнее, поскольку аргумент для второго параметра шаблона задан явно.

3) cond<A<1>>::value оценивается какfalse (т.е. основной выбран).Это мне не понятно.Первичный шаблон дает cond<B, bool_constant<true>>, специализация - cond<B, bool_constant<false>>.Учитывая, что аргумент для второго параметра шаблона явно задан в специализации, почему не является предпочтительным?

Я полагаю, что поведение в (3) связано с некоторым взаимодействием между стандартным аргументом шаблона основного шаблона испециализация.В этом ответе Джерри Коффин заявляет кое-что, что может объяснить это поведение:

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

Может кто-нибудь уточнить это правило?Спасибо

1 Ответ

0 голосов
/ 01 октября 2018
template <typename, typename Enable = bool_constant<true>>
struct cond : public bool_constant<false> {};

идентично

template <typename, typename Enable = bool_constant<true>> struct cond;

template <typename, typename Enable>
struct cond : public bool_constant<false> {};

Позже может быть понятнее понять результат.

Когда вы пишете cond<C>, благодаря аргументу по умолчанию, это эквивалентно cond<C, bool_constant<true>>.

Затем мы пытаемся сопоставить это с «лучшим созданием» .

У нас есть выбор между:

// primary template
template <typename, typename Enable>
struct cond : public bool_constant<false> {};

и частичнымспециализация, использующая SFINAE:

// specialization
template <typename T>
struct cond<T, bool_constant<(0 == T::code)>> : public bool_constant<true> {};

Если 0 == T::code не сформирован, специализация отбрасывается, и только основной шаблон является жизнеспособным решением, поэтому он используется.

Иначе, если 0 == T::code оценивается как false, специализация не соответствует и основной шаблон также используется.
Обратите внимание, что использование cond<C, bool_constant<false>> будет использовать специализацию в этом случае.

Иначе, 0 == T::code оценивается какtrue, и тогда и первичная, и специализация жизнеспособны, но специализация более специализированная, поэтому она выбрана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...