I would like to know if what I am aiming for is possible.
I have a class Class such that
#include<iostream>
template<class T> class Class;
template<class T, class W> Class<W> f(Class<T>& C, const Class<T>& D);
template<class T> class Class {
protected: // this could be private
T m_t;
public:
Class(): m_t(T()) {}
Class(T t): m_t(t) {}
T& getT() { return m_t; }
template<class U, class W> friend Class<W> f(Class<U>& C, const Class<U>& D);
};
template<class T, class W> Class<W> f(Class<T>& C, const Class<T>& D)
{
C.m_t += D.m_t;
Class<W> R;
std::cout << R.m_t << std::endl; // I don't want this to be possible
return R;
}
int main()
{
Class<int> C(42), D(24);
std::cout << f<int, char>(C, D).getT() << std::endl;
}
But this way, f can access private/protected members of instances of Class where Class's type is not the same as f's arguments' type, like in the line
std::cout << R.m_t << std::endl;
(R is of type W, not T)
My question is this: is there a way I can define f as a friend function that has a template parameter specifying the return type (W), but can only access private/protected members of Class objects that are the same type as its arguments' type?
Edit 1: The solution submitted by @cantordust, while clean and aesthetic, doesn't work when Class and f are in a namespace, alas making it unsuitable for more general usecases.
For example, if in a modification of cantordust's code namespace n
starts just after the include declaration, and ends just before the main function, there will be no other way to use f
than to put using n::f;
in main, which, together with its implications, is inexcusable of well-written C++ code.
Edit 2: There is yet another solution: defining a member function, and optionally defining a similar regular function with the same parameters, and calling the member function from it. The code would look something like this:
// inside Class
template<class W> Class<W> f(Class& C, Class& D);
//outside Class
template<class T> template<class W> Class<W> Class<T>::f(Class<T>& C, Class<T>& D)
{ /* definition */ }
The procedure for defining the regular function is obvious.
template<class W> friend Class<W> f<T, W>(Class<T>& C, const Class<T>& D)
I get ther error error: invalid use of template-id‘f<T, W>’
in declaration of primary templatetemplate<class W> friend Class<W> f<T, W>(Class<T>& C, const Class<T>& D);
– Aftermathf
by havingusing N::f
;`. – Frontageusing n::f;
each time the user wants to access what is (should be) just an ordinary function. – Aftermathusing N::f;
) with GCC < 6. – Frontage