问题描述
我想知道我的目标是否可行.
I would like to know if what I am aiming for is possible.
我有一个这样的班级
#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;
}
但是通过这种方式,f可以访问Class实例的私有/受保护成员,其中Class的类型与f的参数的类型不同,例如
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的类型为W,而不是T)
(R is of type W, not T)
我的问题是:有没有一种方法可以将f定义为具有指定返回类型(W)的模板参数的朋友函数,但只能访问与类型相同的Class对象的私有/受保护成员,其参数的类型?
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?
@cantordust提交的解决方案虽然干净美观,但是当Class和f在命名空间中时不起作用,可惜它不适用于更一般的用例.例如,如果在cantordust代码的修改中,namespace n
在include声明之后开始,而在main函数之前结束,那么除了将using n::f;
放入main之外,没有其他方法可以使用f
了,加上其含义,编写良好的C ++代码是不可原谅的.
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.
推荐答案
您可以通过模板类间接访问
You could indirect through a template class
template<class T> class Class;
template<typename>
struct fs;
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; }
friend struct fs<T>;
};
template<typename T>
struct fs
{
template<typename W>
static 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; // ill-formed
return R;
}
};
template<class T, class W>
Class<W> f(Class<T>& C, const Class<T>& D)
{
return fs<T>::template f<W>(C, D);
}
实时.
由于您不能与部分专业知识成为朋友,因此必须使用间接寻址.
The indirection is necessary since you can't befriend a partial specialization.
这篇关于限制多个模板参数友好函数可访问的类实例的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!