Роль параметров шаблона по умолчанию в разрешении перегрузки (частично специализированных) шаблонов классов

Этот ответ объясняет поведение следующей программы:

template<typename A, typename B = int >
struct FirstWins {
    static constexpr int i = 1;
};
template<typename A>
struct FirstWins<A, float/* anything different from int */ > {
    static constexpr int i = 2;
};

template<typename A, typename B = int >
struct SecondWins {
    static constexpr int i = 1;
};
template<typename A>
struct SecondWins<A, int > {
    static constexpr int i = 2;
};

int main()
{
    typedef void Whatever_t;
    cout << FirstWins < Whatever_t >::i << endl;  // prints 1
    cout << SecondWins< Whatever_t >::i << endl;  // prints 2
    return 0;
}

Однако я не могу найти фактическую ссылку, явно описывающую это поведение и, таким образом, подтверждающую ответ.

Я не смог найти на cppreference.com предложение, подтверждающее, что явные аргументы шаблона предпочтительнее аргументов по умолчанию.

Подозреваю, что это не совсем правило. Правило состоит в том, что при наличии частичной специализации шаблона, соответствующей аргументам шаблона, эта специализация всегда предпочтительнее реализации первичного шаблона. Это верно? (в данном случае документы каким-то образом объясняют это правило, но опять же не явно).


person L. Bruce    schedule 07.06.2018    source источник
comment
Параметр по умолчанию просто предоставляет тип, когда код этого не делает. На выбор специализации это не влияет.   -  person Bo Persson    schedule 07.06.2018
comment
Я думаю, вы не понимаете, для чего используются аргументы шаблона по умолчанию. В вашем примере это просто означает, что FirstWins<X> разрешается как FirstWins<X, int>. Фактический выбор определения FirstWins<X, int> происходит после замены B на int.   -  person Holt    schedule 07.06.2018
comment
@Holt: конечно, но мой вопрос действительно касается SecondWins<X, int>. В этом случае SecondWins<X, int> предпочтительнее SecondWins<X, =int>.   -  person L. Bruce    schedule 07.06.2018
comment
@L.Bruce Потому что SecondWins<A, B=int> ничем не отличается от SecondWins<A, B> для выбора шаблона, поэтому специализация SecondsWins<A, int> предпочтительнее неспециализированной. Аргумент шаблона по умолчанию здесь не влияет на разрешение.   -  person Holt    schedule 07.06.2018
comment
@Holt: Ну, я считаю, что в некотором смысле это имеет значение. Посмотрите на FirstWins. Там именно несоответствие между параметром по умолчанию B=int и явным параметром float приводит к выбору первого. B использование по умолчанию всего, что не является float, имеет значение.   -  person L. Bruce    schedule 07.06.2018
comment
@L.Bruce Это влияет на то, на что распространяется FirstWins<X> и SecondWins<X>, вот и все. FirstWins<Whatever_t> распространяется на FirstWins<Whatever_t, int>, что не соответствует специализации, поэтому выбрана неспециализированная версия.   -  person Holt    schedule 07.06.2018


Ответы (1)


template<typename A, typename B = int >
struct S {
//...
};

Можно рассматривать как

template<typename A, typename B = int >
struct S;
// So S<A> is S<A, int>

// Primary template
template<typename A, typename B>
struct S
{
   //...
};

// Possible specialization as
template<typename A>
struct S<A, int>
{
   //...
};

тогда становится более ясно, какой экземпляр использовать.

person Jarod42    schedule 07.06.2018