如何定义类模板的友元函数模板以实现运算符重载

问题描述 投票:0回答:2

我试图在模板类中获取一个友元函数进行编译,但错误消息和警告我不明白。我已经对这个问题进行了演示。我收到的错误是:

prog.cpp:8:57: 错误:非类、非变量部分特化 C 运算符+(const B& lhs, const C& rhs);

prog.cpp:15:59:警告:友元声明 'C 运算符+(const B&, const C&)' 声明一个非模板函数 [-Wnon-template-friend] 友元 C 运算符+(const B& lhs, const C& rhs);

prog.cpp:15:59: 注意:(如果这不是您想要的,请确保函数模板已经声明,并在此处的函数名称后面添加 <>)

#include <iostream>
using namespace std;

template<typename A, typename B>
class C;

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

template<typename A, typename B>
struct C
{
    A val_;
    C operator+(const C& other) const;
    friend C<A, B> operator+(const B& lhs, const C<A, B>& rhs);
};

template<typename A, typename B>
C<A, B> C<A, B>::operator+(const C<A, B>& other) const
{
    C<A, B> c;
    c.val_ = this->val_ + other.val_;
    return c;
}

template<typename A, typename B>
 C<A, B> operator+(const B& lhs, const C<A, B>& rhs)
{
    C<A, B> c;
    c.val_ = lhs + rhs.val_;
    return c;
}

int main() 
{
    C<string, char> c0,c1;
    c0.val_ = " C0 ";
    c1.val_ = " C1 ";
    cout << "Stuct:" << (c0 + c1).val_ << '\n';
    cout << "Friend:" << ('~' + c1).val_ << endl;
    return 0;
}
c++ c++11 templates operator-overloading friend
2个回答
5
投票

最简单的是在类中内联代码:

template <typename A, typename B>
struct C
{
    A val_;
    C operator+(const C& other) const
    {
        C c;
        c.val_ = this->val_ + other.val_;
        return c;
    }

    friend C operator+ (const B& lhs, const C& rhs)
    {
        C c;
        c.val_ = lhs + rhs.val_;
        return c;
    }
};

演示

类中未内联的代码,需要多加注意,因为声明的前向声明顺序,奇怪语法

<>
:

template <typename A, typename B> struct C;

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

template <typename A, typename B>
struct C
{
    A val_;

    friend C<A, B> operator+<> (const B& lhs, const C<A, B>& rhs);

    C operator+(const C& other) const;
};


template <typename A, typename B>
C<A, B> operator+ (const B& lhs, const C<A, B>& rhs)
{
    C<A, B> c;
    c.val_ = lhs + rhs.val_;
    return c;
}

template <typename A, typename B>
C<A, B> C::operator+(const C<A, B>& other) const
{
    C<A, B> c;
    c.val_ = this->val_ + other.val_;
    return c;
}

演示


3
投票

本声明:

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

...是错误的,因为

<A,B>
operator+
之间的
(
,我真的不知道你想在这里做什么。如果您要专业化模板化
operator+
,您会使用此表格,但您不在这里,您是超载

此声明应为:

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

那么您应该在

friend
声明中明确指定您想要一个专门的版本,方法是:

friend C<A,B> operator+<>(const B& lhs, const C<A,B>& rhs);

您需要将其放在

operator+
之前,否则编译器会认为这是非模板化函数的特化。

无论如何,如果你没有真正的理由将代码放在

C
类之外,我会选择@Jarod42解决方案。


你的整个代码应该是这样的:

// Declaration of struct C with delayed definition
template <typename A, typename B>
struct C;

// Initial declaration of templated operator+
template <typename A, typename B>
C<A, B> operator+ (const B&, const C<A, B>&);

// Definition of C
template <typename A, typename B>
struct C {

    friend C operator+<> (const B&, const C&);

    // This must be AFTER the templated operator+
    C operator+ (const C&) const;
};

template<typename A, typename B>
C<A, B> C<A, B>::operator+(const C<A, B>& other) const {

}

template<typename A, typename B>
C<A, B> operator+(const B& lhs, const C<A, B>& rhs) {

}
© www.soinside.com 2019 - 2024. All rights reserved.