1

i m trying to create a Set class ( using template so ). The problem i get is when i try to overload operator<<. I tried define my function as friend of class Set but it doesn t work. I got this error: error: 'std::set, std::allocator > Set::m_set' is private

Here is my code:

#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

It seems the problem is that i m trying to access allocator from the default set class, but I don t really know where am i trying to use this ... Did someone know how to use that correctly ? Shoudl I redefine a new allocator ? ( If possible i d like to keep this organisation of code (it s a school work so i have criteria to respect :/ ) I m new on c++ and i never used template before :/ Sorry guys for my approximate english, and i already thank you for the help :)

Vrael
  • 77
  • 6

3 Answers3

3

You need to change the friend from :

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

to

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

because when you make friend operator with Set<T> instead of Set<U> and having instance of Set<int> (for example) you refer to a operator << for int specifically:

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

and the templated version is totally different function from the above one:

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

Edit: It depends on what you want, if you want o make the friend the operator specific for your type T, then use need to use Set<T> and declare the operator for your type T (int, float or whatever type you instantiated Set and used operator <<), not the templated version. If you want to make the templated version friend then you need to use Set<U>

Raxvan
  • 6,257
  • 2
  • 25
  • 46
  • The caveat is that this makes all template instantiations of the operator friends of any given instantiation of the `Set` class template . – juanchopanza Dec 16 '13 at 14:01
1

The first problem that you have is that the operator is not the right one. You don't want an operator templated in a type U where the U cannot be deduced, you might have meant to have the second argument be Set<U>, rather than Set<T>.

That being said, you are probably better off not befriending a template operator at all, but rather befriending a non-template function, which you can define inside the class definition.

template <typename T>
class Set {
//...
    friend std::ostream& operator<<(std::ostream& o, const Set& s) { ... }
};

Which, considering that all of the member functions are defined inline should not be a problem.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
0

Thank you guys for being so fast to answer :) Changing to this

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

is not working on my case because (I think) I need to define operator<<`as a non-member function. But the other proposition seems to work fine:

template<class U> friend ostream& operator<<(ostream &, const Set<U> &);
Vrael
  • 77
  • 6