I have a template class that defines a subtype. I'm trying to define the binary operator+
as a template function, but the compiler cannot resolve the template version of the 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 operat开发者_运维问答or+(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;
}
I think the reason is because the compiler (g++4.3) cannot guess the template type so it's searching for operator+<int>
instead of operator+
.
What's the reason for that? What elegant solution can you suggest?
Your suspicion is correct. The compiler doesn't know what other_type
is. It can't deduce it from the arguments. Such forms often are too loose to provide the needed informations. Consider
template<typename other_type>
struct c {
c(other_type v) : cs(v) {}
typedef int subtype;
};
If you were to pass an int
, then any of c<T>
would fit the bill because all of them have type int
. In the specific case of nested classes, it may be possible, but even then it's not unique. Imagine that in c<float>
you could put a typedef c<int> subtype;
, then both c<float>::subtype
and c<int>::subtype
would fit the bill.
Back in pre-standard time, there existed a list of template-issues that in particular John Spicer did go through and invented reasonable solutions. That was one such problem, and it was found that it's not worth the trouble. You always explicitly need to provide the argument - it's never deduced.
You could change your code to this
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); }
Or to this
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;
};
精彩评论