How do I overload operator+ for inner class of a class template? I've searched for hours now and I can't find an answer. This is a minimal example that does not work:
#include <iostream>
using namespace std;
template <class T>
struct A
{
struct B
{
T m_t;
B(T t) : m_t(t) {}
};
};
template <class T>
typename A<T>::B operator+(typename A<T>::B lhs, int n)
{
lhs.m_t += n;
return lhs;
}
int main(int argc, char **argv)
{
A<float> a;
A<float>::B b(17.2);
auto c = b + 5;
cout << c.m_t << endl;
return 0;
}
If I compile like this, I get error: no match for ‘operator+’ (operand types are ‘A<float>::B’ and ‘int’)
I found somewhere that operator+(A<T>::B, int)
should be declared, so if I add the following:
struct B;
friend B operator+(typename A<T>::B lhs, int n);
after struct A {
, I get a linker error.
If I don't try to call b+5, the program compiles correctly.
How did they (STL makers) program vector<T>::iterator operator+
with an int? I can't find it anywhere (and it's kind of hard to read stl_vector.h)!
Thank you.
The problem you're facing is that when you declare a function template like:
template <class T>
typename A<T>::B operator+(typename A<T>::B lhs, int n)
typename A<T>::B lhs
is a non-deduced context. There is no way for the compiler to determine what T
is in that context, so it doesn't try, so it cannot find your operator+
. Consider a reduced example like:
template <class T> void foo(typename T::type );
struct A { using type = int; };
struct B { using type = int; };
foo(0); // what would T be?
// how many other possible T's are there that fit?
In order for template deduction to succeed with non-deduced contexts, the template type parameter must be explicitly specified. In this case, this monstrosity of a syntax compiles:
auto c = ::operator+<float>(b, 5);
But probably isn't your intended usage!
You will need to declare the operator+
within struct B
:
struct B
{
T m_t;
B(T t) : m_t(t) {}
// member
B operator+(int n) {
return B(m_t + n);
}
// or non-member, non-template friend
friend B operator+(B lhs, int n) {
lhs.m_t += n;
return lhs;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With