I have a class that overloads the bit shift operator like the following:
template<typename DataType>
friend Packet& operator << (Packet& pkt, const DataType& data)
{
std::cout << "this compiles" << std::endl;
}
but when I try to make a specialization of it like this :
template<typename DataType>
friend Packet& operator << (Packet& pkt, const DataType& data)
{
std::cout << "this doesn't compile" << std::endl;
}
template<>
friend Packet& operator<<<std::string> (Packet& pkt, const std::string& data)
{
std::cout << "this doesn't compile" << std::endl;
}
it throws a compile time error:
Error C2116 'operator <<': function parameter lists do not match between declarations
what I'm I doing wrong here ?
CodePudding user response:
If I get you correctly, following is what you want to achieve right?
#include <iostream>
class Packet
{
public:
template<class T>
friend Packet& operator << (Packet& pkt, const T& data);
};
template<class DataType>
Packet& operator << (Packet& pkt, const DataType& data)
{
std::cout << "primary" << std::endl;
return pkt; // handle it as as per your logic
}
template<>
Packet& operator<< (Packet& pkt, const std::string& data)
{
std::cout << "specialisation for std::string" << std::endl;
return pkt; // handle it as as per your logic
}
int main()
{
Packet p1;
p1<<4;
p1<<std::string("samplestring");
return 0;
}
CodePudding user response:
How do I make C friend template specializations work?
A friend template can declare only primary templates and members of primary templates. Any partial specializations and explicit specializations associated with a primary template are automatically considered friends too.
So to solve the problem in your code, you can add a friend template declaration for the primary template inside class Packet
and then define that primary template as well as any other specialization outside the class as shown below:
#include <iostream>
#include<string>
struct Packet
{
//friend template declaration for primary template
template<typename DataType>
friend Packet& operator << (Packet& pkt, const DataType& data);
};
//implementation of primary template
template<typename DataType>
Packet& operator << (Packet& pkt, const DataType& data)
{
std::cout << "primary template called" << std::endl;
return pkt;
}
//implementation of explicit specialization
template<>
Packet& operator<<<std::string> (Packet& pkt, const std::string& data)
{
std::cout << "specialization for std::string called" << std::endl;
return pkt;
}
int main()
{
Packet p;
p << 100; //uses primary template
std::string s("someString");
p << s; //uses specialization for std::string
return 0;
}
The changes that i made include:
- Added a friend template declaration for the primary template inside
Packet
. - Added implementation for both the primary template as well as explicit specialization outside the class
Packet
. Note that there is no need for thefriend
keyword in the implementation outside class. Moroever, the explicit specialization is automatically a friend ofPacket
so no need to have a friend declaration for this specialization inside the classPacket
. - Added return statement that were missing in the original example question.