I have a template class called "KeyedCollection" that contains functions to insert data into a vector, as well as stream out the data. The vector is a private member function. I can't seem to figure out how to use the information from this vector in my overloading ostream friend function. Note: I cannot change the general structure of the class and the function arguments, they have to stay as they are. I list all of the class for reference, but the function in question is the last one.
#include "stdafx.h"
#include <iostream>
#include <vector>
#include "Windows.h"
#include <string>
using namespace std;
template <class K, class T>
class KeyedCollection {
public:
// Create an empty collection
KeyedCollection();
// Return the number of objects in the collection
int size() const;
// Insert object of type T with a key of type K into the
// collection using an “ignore duplicates” policy
void insert(const K&, const T&);
// Output data value of objects in the collection,
// one data value per line
friend ostream& operator<<(ostream&,
const KeyedCollection&);
private:
// Insert required members here
int objSize;
vector<T> objects;
};
template<class K, class T>
KeyedCollection<K,T>::KeyedCollection() {
objSize = 0;
vector<T> objects;
}
template<class K, class T>
int KeyedCollection<K,T>::size() const {
objSize = objects.size();
return objSize;
}
template<class K, class T>
void KeyedCollection<K,T>::insert(const K&,const T& c) {
objects.push_back(c);
}
// !!! function i am trying to define !!!
template<class K, class T>
ostream& operator<<(ostream& outstream,const KeyedCollection<K,T>& inst) {
outstream<<inst<<endl;
return outstream;
}
Also, I'm getting an error that says
"fatal error LNK1120: 1 unresolved externals"
and one that says
"error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class KeyedCollection const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$KeyedCollection@HVCustomer@@@@@Z) referenced in function _main" ...
Just as a side question, any idea what those could be?
cppreference and Johannes Schaub - litb both provide the same method for getting this to work.
You want to make one single instance (called "specialization" in generic terms) of that template a friend. You do it the following way [...]
First make a forward declaration before the definition of your class:
template <class K, class T> class KeyedCollection;
template<class K, class T>
ostream& operator<<(ostream& outstream,const KeyedCollection<K,T>& inst);
Because the compiler knows from the parameter list that the template arguments are T and U, you don't have to put those between <...>, so they can be left empty.
Then make your friend declaration and be sure to add <>
after operator<<
:
template <class K, class T>
class KeyedCollection {
public:
// snip
friend ostream& operator<< <> (ostream& outstream,const KeyedCollection<K,T>& inst);
// snip
};
Finally you can define it:
template<class K, class T>
ostream& operator<<(ostream& outstream,const KeyedCollection<K,T>& inst) {
// Just an example
for (const auto& t : inst.objects)
{
std::cout << t << std::endl;
}
return outstream;
}
Alternately, do what Yakk suggested.
template <class K, class T>
class KeyedCollection {
public:
// snip
friend ostream& operator<<(ostream& outstream,const KeyedCollection<K,T>& inst) {
for (const auto& t : inst.objects)
{
std::cout << t << std::endl;
}
return outstream;
}
// snip
};