C++ 模板运算符 + 内部类中的重载

C++ template operator+ overloading in inner class

本文关键字:重载 内部类 运算符 C++      更新时间:2023-10-16

如何为类模板的内部类重载运算符+?我已经搜索了几个小时,但找不到答案。这是一个不起作用的最小示例:

#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)!

谢谢。

您面临的问题是,当您声明如下函数模板时:

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);

但可能不是您的预期用途!

<小时 />

您需要在struct B内声明operator+

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;
    }
};

也许你可以做这样的事情:

#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