Ваше подозрение верно. Компилятор не знает, что такое other_type
. Это не может быть выведено из аргументов. Такие формы часто слишком свободны для предоставления необходимой информации. Рассмотрим
template<typename other_type>
struct c {
c(other_type v) : cs(v) {}
typedef int subtype;
};
Если вы передадите int
, то любой из c<T>
будет соответствовать требованиям, поскольку все они имеют тип int
. В конкретном случае вложенных классов это может быть возможно, но даже тогда это не уникально. Представьте, что в c<float>
вы можете поставить typedef c<int> subtype;
, тогда и c<float>::subtype
, и c<int>::subtype
будут соответствовать требованиям.
В предстандартное время существовал список проблем с шаблонами, которые, в частности, Джон Спайсер прошел и изобрел разумные решения. Это была одна из таких проблем, и было установлено, что это не стоит проблем. Вы всегда должны явно указать аргумент - он никогда не выводится.
Вы можете изменить свой код на этот
template<typename other_type>
struct subtype {
subtype(other_type v) : val(v) {}
other_type val;
};
template<typename other_type>
struct c {
c(other_type v) : cs(v) {}
subtype<other_type> cs;
};
template<typename other_type>
subtype<other_type> operator+(const subtype<other_type>& left,
const subtype<other_type>& right)
{ return subtype<other_type>(left.val + right.val); }
Или к этому
template<typename other_type>
struct c {
c(other_type v) : cs(v) {}
struct subtype {
subtype(other_type v) : val(v) {} other_type val;
/* note: don't forget friend! */
friend subtype operator+(const subtype& left,
const subtype& right)
{ return subtype(left.val + right.val); }
} cs;
};