Stef
Stef

Reputation: 3

Simple template class with overloaded << operator fails, "Invalid use of template-id"

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

Answers (2)

claytonjwong
claytonjwong

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

Daniel
Daniel

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

Related Questions