【问题标题】:C++ template operator+ overloading in inner class内部类中的 C++ 模板运算符重载
【发布时间】:2016-02-23 16:34:47
【问题描述】:

如何为类模板的内部类重载 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&lt;float&gt;::B’ and ‘int’)

我发现应该声明operator+(A&lt;T&gt;::B, int),所以如果我添加以下内容:

struct B;
friend B operator+(typename A<T>::B lhs, int n);

struct A { 之后,我得到一个链接器错误。

如果我不尝试调用 b+5,程序编译正确。

他们(STL 制造商)如何使用 int 对 vector&lt;T&gt;::iterator operator+ 进行编程?我在任何地方都找不到它(而且有点难以阅读 stl_vector.h)!

谢谢。

【问题讨论】:

  • 没有继承,你所谓的“子”类我宁愿叫“内”/“嵌套”类
  • 您是否尝试将运算符作为成员函数?
  • T in typename A&lt;T&gt;::B lhs 是不可演绎的,因此此重载对于调用不可行

标签: c++ templates operator-overloading


【解决方案1】:

你面临的问题是当你声明一个函数模板时:

template <class T>
typename A<T>::B operator+(typename A<T>::B lhs, int n)

typename A&lt;T&gt;::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;
    }
};

【讨论】:

    【解决方案2】:

    也许你可以这样做:

    #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&lt;is_same&lt;T, typename T::OuterType::B&gt;::value, T&gt;::type 而不是结果类型来测试此结构是否与 T 相同:typename T::OuterType::B

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      • 2012-11-14
      • 2016-06-26
      • 1970-01-01
      相关资源
      最近更新 更多