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 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;
}
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_typeis. It can’t deduce it from the arguments. Such forms often are too loose to provide the needed informations. ConsiderIf you were to pass an
int, then any ofc<T>would fit the bill because all of them have typeint. In the specific case of nested classes, it may be possible, but even then it’s not unique. Imagine that inc<float>you could put atypedef c<int> subtype;, then bothc<float>::subtypeandc<int>::subtypewould 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
Or to this