NOTE: this post is different from this one: Declare non-template friend function for template class outside the class, so please read my question before marking it as duplicate.
I want to declare a non-template friend function inside a class template, and the arguments and return type of that friend function is unrelated to the template argument. How should I do that?
Please note it is different from that previous question because in that question, arguments and return type of that friend function is related to the template argument.
Example, adapted from that question above:
// class.h
#include <iostream>
using namespace std;
template <typename T>
struct B
{
T value;
int value2;
B() : value2(1) {}
friend void modify(const int&); // unrelated to T!
void printValue2() {
modify(value2);
cout << value2 << endl;
}
};
// define friend function foo() in a class.cpp file, not in the header
void modify(const int &v) { v = v * 2 + 1; } // HOW should I write it?
// main.cpp
int main() {
B<int> b;
b.printValue2();
return 0;
}
I know I can declare modify()
outside this template class so it becomes a vanilla, ordinary function. But I want only this template class to have access to modify()
. Alternatively, to achieve this goal of access control, I could define modify()
to be a static method in this template class, but that would make the method a template method, forcing me to define it in the header.
Followup: if the friend approach above doesn't work, how should I achieve the two goals at the same time:
modify()
modify()
in a *.cpp file, rather in a header.Accepted Answer:
To achieve the two goals above, don't abuse friendship.
The best practice is let the class template privately inherit a non-template base class, and in that base class declare common non-template methods that are unrelated to template arguments.
Therefore, you are able to define these methods in a separate *.cpp file, reducing the header's size.
You might use private inheritance instead of friendship:
// class.h
#include <iostream>
class B_helper
{
protected:
static void modify(int &v);
};
template <typename T>
struct B : private B_helper
{
T value;
int value2;
B() : value2(1) {}
void printValue2() {
modify(value2);
std::cout << value2 << std::endl;
}
};
// class.cpp
void B_helper::modify(int &v) { v = v * 2 + 1; }