限制多个模板参数友元函数可访问的class个实例的范围
Restrict the scope of class instances accessible by multiple template parameter friend function
我想知道我的目标是否可行。
我有一个 class Class 这样
#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 实例的 private/protected 成员,其中 Class 的类型与 f 的参数类型不同,如行
std::cout << R.m_t << std::endl;
(R是W类型,不是T)
我的问题是:有没有一种方法可以将 f 定义为一个友元函数,它有一个指定 return 类型 (W) 的模板参数,但只能访问 private/protected 的成员Class 个与其参数类型相同的对象?
编辑 1:@cantordust 提交的解决方案虽然干净美观,但当 Class 和 f 在命名空间中时不起作用,唉,使其不适合更一般的用例。
例如,如果在对 cantordust 代码的修改中 namespace n
在 include 声明之后开始,并在 main 函数之前结束,那么除了将 using n::f;
在 main 中,连同它的含义,对于编写良好的 C++ 代码来说是不可原谅的。
编辑 2:还有另一种解决方案:定义一个成员函数,并可选择地定义一个具有相同参数的类似常规函数,并从中调用成员函数。
代码看起来像这样:
// 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 */ }
定义正则函数的过程很明显。
您可以通过模板间接访问 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);
}
Live.
间接是必要的,因为你不能与部分专业化成为朋友。
在温和的假设下,您不需要辅助结构:
#include<iostream>
template<class T> class Class;
template<typename U, typename W>
Class<W> f(Class<U>& C, const Class<U>& 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<typename U, typename W>
friend 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;
}
我想知道我的目标是否可行。
我有一个 class Class 这样
#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 实例的 private/protected 成员,其中 Class 的类型与 f 的参数类型不同,如行
std::cout << R.m_t << std::endl;
(R是W类型,不是T)
我的问题是:有没有一种方法可以将 f 定义为一个友元函数,它有一个指定 return 类型 (W) 的模板参数,但只能访问 private/protected 的成员Class 个与其参数类型相同的对象?
编辑 1:@cantordust 提交的解决方案虽然干净美观,但当 Class 和 f 在命名空间中时不起作用,唉,使其不适合更一般的用例。
例如,如果在对 cantordust 代码的修改中 namespace n
在 include 声明之后开始,并在 main 函数之前结束,那么除了将 using n::f;
在 main 中,连同它的含义,对于编写良好的 C++ 代码来说是不可原谅的。
编辑 2:还有另一种解决方案:定义一个成员函数,并可选择地定义一个具有相同参数的类似常规函数,并从中调用成员函数。 代码看起来像这样:
// 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 */ }
定义正则函数的过程很明显。
您可以通过模板间接访问 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);
}
Live.
间接是必要的,因为你不能与部分专业化成为朋友。
在温和的假设下,您不需要辅助结构:
#include<iostream>
template<class T> class Class;
template<typename U, typename W>
Class<W> f(Class<U>& C, const Class<U>& 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<typename U, typename W>
friend 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;
}