重载operator+模板导致未解决的外部符号错误

3

我正在尝试为类模板重载'+'运算符,但在使用中缀表示法调用它时出现了未解决的外部符号错误:

// In main.cpp

template<class T>
struct B
{
    B(T t) : t_(t) {}
    friend B operator+(B const &lhs, B const &rhs);
    T t_;   
};

template<class T>
B<T> operator+(B<T> const &lhs, B<T> const &rhs)
{
    return B<T>(lhs.t_ + rhs.t_);
}

int main()
{
    B<int> b = 1;
    b = operator+<int>(b, 2); // works but clunky syntax
    // b = b + 2; // LNK2019: unresolved external symbol
}

对于常规非模板类很好用,因此想知道能否在这里实现相同的效果。

我正在使用Visual C++ 2015。


1
“friend B operator+(B const &lhs, B const &rhs);” 不是一个模板声明,但你却定义了一个。 - LogicStuff
请参见https://dev59.com/6WfWa4cB1Zd3GeqPdAo-。 - M.M
顺便提一下,目前所有成员都是“public”,所以不需要“friend”;-) - Jarod42
1
明白了,感谢您的帮助。如果还有其他人看到这条信息,我也发现http://web.mst.edu/~nmjxv3/articles/templates.html非常有用。 - George Skelton
@GeorgeSkelton 的评论指向模板文章非常好。那篇文章很好地解释了问题/选项,让人易于理解。 - aggieNick02
2个回答

4
friend B operator+(B const &lhs, B const &rhs);

这是一个非模板函数。

更简单的方法是将其定义为 inline

template<class T>
struct B
{
    B(T t) : t_(t) {}
    friend B operator+(B const &lhs, B const &rhs)
    {
       return B(lhs.t_ + rhs.t_);
    }
    T t_;   
};

演示

否则,您必须声明所有模板友元。

template <typename T> struct B;

template <typename T> B<T> operator+(B<T> const &lhs, B<T> const &rhs);

template<class T>
struct B
{
    B(T t) : t_(t) {}

    template <typename U>
    friend B<U> operator+(B<U> const &lhs, B<U> const &rhs);
    T t_;   
};

演示

或者只是具体的一个

template <typename T> struct B;

template <typename T> B<T> operator+(B<T> const &lhs, B<T> const &rhs);

template<class T>
struct B
{
    B(T t) : t_(t) {}
    friend B operator+<>(B const &lhs, B const &rhs);
    // Note the <>

    T t_;   
};

template<class T>
B<T> operator+(B<T> const &lhs, B<T> const &rhs)
{
    return B<T>(lhs.t_ + rhs.t_);
}

演示


定义内联函数可以工作,但我想避免这样做,因为我的真实类里面有更多的东西。我发现我没有定义模板函数,但是我尝试了你的解决方案,在两种情况下都得到了“C2678:二进制“+”:没有找到接受左操作数类型为'B<int>'的运算符(或者没有可接受的转换)”。 - George Skelton
@GeorgeSkelton:我添加了链接。 - Jarod42
啊,好的,我明白你的意思了,谢谢。但是它仍然无法编译 b + 1,因为它无法从 int 推断出 B<int>。然而,成员函数可以进行这样的推断。这只是友元函数的固有限制吗? - George Skelton
模板的“限制”。如何知道哪个模板是从 int 构建的?您知道只有 B<int> 有正确的构造函数,但它们可能有特化等。 - Jarod42

0

你还没有在类内定义它作为一个模板。 最简单的解决方案是在类内定义函数(内联):

template<class T>
struct B
{
    B (T t) : t_ (t) {}
    friend B operator+ (const B &lhs, const B &rhs)
    {
       return B (lhs.t_ + rhs.t_);
    }
    T t_;   
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接