我有一个定义子类型的模板类。我正在尝试将二进制operator+
定义为模板函数,但编译器无法解析operator+
的模板版本。
#include <iostream>
template<typename other_type>
struct c {
c(other_type v) : cs(v) {}
struct subtype { subtype(other_type v) : val(v) {} other_type val; } cs;
};
template<typename other_type>
typename c<other_type>::subtype operator+(const typename c<other_type>::subtype& left,
const typename c<other_type>::subtype& right)
{ return typename c<other_type>::subtype(left.val + right.val); }
// This one works
// c<int>::subtype operator+(const c<int>::subtype& left,
// const c<int>::subtype& right)
// { return c<int>::subtype(left.val + right.val); }
int main()
{
c<int> c1 = 1;
c<int> c2 = 2;
c<int>::subtype cs3 = c1.cs + c2.cs;
std::cerr << cs3.val << std::endl;
}
我认为原因是因为编译器(g ++ 4.3)无法猜测模板类型,因此它正在搜索operator+<int>
而不是operator+
。
这是什么原因?你能提出什么样的优雅解决方案?
答案 0 :(得分:4)
你的怀疑是正确的。编译器不知道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
都符合要求。
早在标准时间之前,就存在一个模板问题列表,特别是John Spicer确实经历过并发明了合理的解决方案。这是一个这样的问题,并且发现它不值得麻烦。你总是明确需要提供论证 - 它永远不会被推断出来。
您可以将代码更改为此
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;
};