如何为类模板的内部类重载operator +?我现在已经搜索了几个小时,但我找不到答案。这是一个不起作用的最小示例:
#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;
}
如果我这样编译,我会得到error: no match for ‘operator+’ (operand types are ‘A<float>::B’ and ‘int’)
我找到了应该声明operator+(A<T>::B, int)
的地方,所以如果我添加以下内容:
struct B;
friend B operator+(typename A<T>::B lhs, int n);
在struct A {
之后,我收到链接器错误。
如果我不尝试拨打b + 5,程序会正确编译。
他们(STL制造商)如何使用int编程vector<T>::iterator operator+
?我无法在任何地方找到它(并且它很难读取stl_vector.h)!
谢谢。
答案 0 :(得分:2)
您面临的问题是当您声明一个功能模板时:
template <class T>
typename A<T>::B operator+(typename A<T>::B lhs, int n)
typename A<T>::B lhs
是非推断的上下文。编译器无法确定该上下文中的T
,因此它不会尝试,因此无法找到您的operator+
。考虑一个简化的例子,如:
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?
为了使模板推导成功使用非推导的上下文,必须明确指定模板类型参数。在这种情况下,语法的这种怪异性会编译:
auto c = ::operator+<float>(b, 5);
但可能不是您的预期用途!
您需要在operator+
:
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;
}
};
答案 1 :(得分:0)
也许你可以这样做:
#include <iostream>
#include <type_traits>
using namespace std;
template <class T>
struct A
{
struct B
{
typedef A<T> OuterType;
T m_t;
B(T t) : m_t(t) {}
};
};
template <class T>
typename T::OuterType::B operator+(T 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;
}
编辑:这将起作用,因为T可以从表达式(b + 5)
的第一个操作数中删除,并且仅适用于包含OuterType
结构的结构,该结构定义了子类型B为内部结构。您可以使用typename enable_if<is_same<T, typename T::OuterType::B>::value, T>::type
而不是结果类型来测试此结构是否与T相同:typename T::OuterType::B