重载运算符<<用于模板类。即使有朋友关键字,也无法获得私人会员

时间:2013-12-16 13:51:12

标签: c++ templates friend

我正在尝试创建一个Set类(使用模板)。我得到的问题是当我尝试重载运算符<<。我尝试将我的函数定义为类Set的朋友,但它不起作用。我收到了这个错误: 错误:'std :: set,std :: allocator> Set :: m_set'是私有的

这是我的代码:

#ifndef GUARD_set_h
#define GUARD_set_h

#include <iostream>
#include <array>
#include <vector>
#include <set>
#include <string>

using namespace std;

template <class T>
class Set
{ 

public:
Set() {} // est ce vraiment requis de l'écrire ? je pense qu oui mais a verif ou copy ?

Set(const T arr[], size_t arr_sz) // voir si operator= n est pas mieu ou copy ?
{
    for(size_t i = 0; i < arr_sz; ++i)
        m_set.insert(arr[i]);
}

Set(const vector<T>& vec)
{
    for(size_t i = 0; i < vec.size(); ++i)
        m_set.insert(vec[i]);
}

Set(const set<T>& st) 
{
    m_set = st;
}

Set(const Set& set_to_copy)
{
    m_set = set_to_copy.m_set;
}



void insert(const T& elem)
{
    m_set.insert(elem);
}

void remove(const T& elem)
{
    m_set.erase(elem);
}

size_t cardinality() const 
{
    return m_set.size();
}

bool isEmpty() const 
{
    return m_set.empty();
}

/** DEBUT OPERATORS **/

Set& operator +=(const Set& st)
{
    for (typename set<T>::iterator it = st.m_set.begin(); it != st.m_set.end(); ++it)
        m_set.insert(*it);
    return *this;
}


template<class U> friend ostream& operator<<(ostream &, const Set<T> &);

private:
set<T> m_set;
};


/** Non-Member Operators **/
template <typename T>
Set<T> operator+(Set<T> st1, const Set<T>& st2) // Set Union
{
    Set<T> set_to_copy(st1);
    set_to_copy += st2;
    return set_to_copy;
}

template <typename T>
Set<T> operator -(Set<T> st1, const Set<T>& st2) // Union Complement
{
    Set<T> set_to_copy(st1);
    set_to_copy -= st2;
    return set_to_copy;
}

template <class T>
ostream& operator<<(ostream &out, const Set<T> &st)
{
    for (typename set<T>::iterator it = st.m_set.begin(); it != st.m_set.end(); ++it)
        out << ' ' << *it;
    cout << '\n';
    return out;
}
#endif

似乎问题是我试图从默认的set类访问allocator,但我真的不知道我在哪里尝试使用它... 有人知道如何正确使用它吗? Shoudl我重新定义了一个新的分配器? (如果可能的话,我想保留这个代码组织(这是学校的工作,所以我有尊重的标准:/) 我是c ++的新手,我之前从未使用过模板:/ 对不起,我的近似英语,我已经感谢你的帮助了:))

3 个答案:

答案 0 :(得分:3)

您需要更改朋友:

template<class U> friend ostream& operator<<(ostream &, const Set<T> &);

// use Set<U> instead of Set<T>
template<class U> friend ostream& operator<<(ostream &, const Set< U > &);//U instead of T

因为当您使用Set<T>代替Set<U>并且拥有Set<int>实例的朋友运算符时(例如),您特别为int引用operator <<

ostream& operator<<(ostream &, const Set<int> &){}

和模板化版本与上面的版本完全不同:

template <class T>
ostream& operator<<(ostream &, const Set<T> &){}

编辑:这取决于你想要什么,如果你想让朋友为你的类型T特定的操作符,那么使用需要使用Set<T> 并为你的类型T声明操作符(int ,float或您实例化的任何类型设置和使用运算符&lt;&lt;),而不是模板化版本。如果您想制作模板版本的朋友,那么您需要使用Set<U>

答案 1 :(得分:1)

您遇到的第一个问题是操作员不是正确的操作员。您不希望在无法推导出U的{​​{1}}类型中模板化运算符,您可能打算让第二个参数为U,而不是Set<U>

话虽这么说,你可能最好不要与模板运算符交朋友,而是与非模板函数建立联系,你可以在类定义中定义它。

Set<T>

其中,考虑到所有成员函数都是内联定义的应该不是问题。

答案 2 :(得分:0)

谢谢你们这么快回答:)改为这个

friend ostream& operator<<(ostream &, const Set<T> &);`

不能处理我的情况,因为(我认为)我需要将operator&lt;&lt;`定义为非成员函数。但另一个命题似乎运作良好:

template<class U> friend ostream& operator<<(ostream &, const Set<U> &);