Reputation: 3
I'm trying to overload the stream output operator for a template class of mine. I've been running into all sorts of trouble with undefined references and now the error
"invalid use of template-id 'operator<< <>' in declaration of primary template"
I've read every Stackoverflow and other forum post i could find on the correct declaration, and there seem to be multiple ways people manage my desired result. Could anyone please help me understand what is going wrong?
The .h file:
//class must be forward declared because it contains a friend function template
template<class T> class messageTemplate;
//friend function also must be forwards declared
template<class A> std::ostream &operator<<(std::ostream &os, messageTemplate<A> &aTemplate);
template <class T>
class messageTemplate {
public:
messageTemplate(const std::string &topic, T data);
template <class A>
friend std::ostream &operator<< <>(std::ostream &os, messageTemplate<A> &aTemplate);
private:
std::string topic;
T data;
};
the .cpp:
template class messageTemplate<int>;
template class messageTemplate<double>;
template class messageTemplate<std::string>;
template class messageTemplate<bool>;
template<class T>
messageTemplate<T>::messageTemplate(const std::string &topic, T data):topic(topic), data(data) {};
template <class T>
std::ostream &operator<< (std::ostream &os, messageTemplate<T> &aTemplate) {
os << "topic: " << aTemplate.topic << " data: " << aTemplate.data;
return os;
};
At this point i've tried and applied so many solutions I feel like starting from scratch might be better.
Full error message (happens at the declaration in het .h file):
error: invalid use of template-id 'operator<< <>' in declaration of primary template friend std::ostream &operator<< <>(std::ostream &os, messageTemplate &aTemplate);
Upvotes: 0
Views: 827
Reputation: 844
There are two problems I see:
1) the overloaded function declaration for operator<< contains the characters <>
which causes a compile failure. This can be fixed by removing <>
2) the overloaded function definition for operator<< ( and the class ctor ) exists in a source file which causes a linker failure. This can be fixed by moving these definitions from the source file to the header file.
Try using the following header and source files, this works for me...
template.h
#pragma once
#include <iostream>
#include <string>
//class must be forward declared because it contains a friend function template
template<class T> class messageTemplate;
//friend function also must be forwards declared
template<class A> std::ostream &operator<<(std::ostream &os, messageTemplate<A> &aTemplate);
template <class T>
class messageTemplate {
public:
messageTemplate(const std::string &topic, T data);
template <class A>
friend std::ostream &operator<<(std::ostream &os, messageTemplate<A> &aTemplate);
private:
std::string topic;
T data;
};
template<class T>
messageTemplate<T>::messageTemplate(const std::string &topic, T data):topic(topic), data(data) {};
template <class T>
std::ostream &operator<< (std::ostream &os, messageTemplate<T> &aTemplate) {
os << "topic: " << aTemplate.topic << " data: " << aTemplate.data;
return os;
};
main.cpp
#include "template.h"
#include <iostream>
using namespace std;
int main()
{
messageTemplate< int > test{ "test", 69 };
cout << test << endl;
return 0;
}
Console output:
topic: test data: 69
Process finished with exit code 0
Upvotes: 1
Reputation: 854
Ostensibly, the problem is you're trying to overload not the operator "<<", but the operator "<< <>"
From the .h file, replace
friend std::ostream &operator<< <>(std::ostream &os, messageTemplate<A> &aTemplate);
with
friend std::ostream &operator<< (std::ostream &os, messageTemplate<A> &aTemplate);
Upvotes: 0