В соответствии с пунктом 14.8.2.1 стандарта C ++, когда параметр шаблона используется только в не выводимом контексте, соответствующий аргумент шаблона не может быть выведен:
Если шаблон-параметр не используется ни в одном из параметров функции шаблона функции или используется только в не выводимом контексте, соответствующий ему шаблон-аргумент не может быть выведен из вызова функции, и шаблон-аргумент должен быть явно указан.
Определение не выводимых контекстов, как указано в §14.8.2.4:
Неопределенные контексты:
спецификатор вложенного имени типа, указанного с помощью qualid-id .
Тип, который представляет собой template-id , в котором один или несколько из template-arguments является выражением, которое ссылается на template-параметр .
В Bar<T>::type
, Bar<T>
является спецификатором вложенного имени и, следовательно, не выводимым контекстом, поэтому вы должны явно указать аргумент шаблона при вызове конструктора ... который не является возможно (т.е. вы не можете написать Foo f<int>(v)
).
Полагаю, компилятор не может вывести аргумент шаблона, потому что это было бы по меньшей мере громоздко и, скорее всего, невозможно: представьте, что Bar специализирован:
template<typename T>
struct Bar
{
typedef std::pair<T,T> type;
};
template<>
struct Bar<char>
{
typedef std::pair<int,int> type;
};
Теперь у меня есть неоднозначность при вызове конструктора Foo с помощью std::vector<std::pair<int,int> >
: должен ли аргумент шаблона быть int
или char
? И даже если бы не было такой неоднозначности, вы можете легко увидеть, что компилятору пришлось бы создавать экземпляры Bar с потенциально любым типом, прежде чем найти экземпляр с правильным typedef (ну, я не уверен, что приведенные выше утверждения действительно актуальны, так как я часто узнайте, что компиляторы намного умнее, чем я думал: -)!)