C++模板:部分模板规范和友元类
C++ Templates: Partial Template Specifications and Friend Classes
是否有可能以某种方式使部分模板规范成为友元类? 即考虑您有以下模板类
template <class T> class X{
T t;
};
现在您有部分专用化,例如,对于指针
template <class T> class X<T*>{
T* t;
};
我想要实现的是,每个可能的X<T*>
都是任何S
的朋友类X<S>
。 X<A*>
应该是X<B>
的朋友.
当然,我想到了 X 中一个常用的模板好友声明:
template <class T> class X{
template <class S> friend class X<S*>;
}
但是,这不能编译,g++ 告诉我:
test4.cpp:34:15:错误:"template<class T> class X
"的专用化必须出现在命名空间范围内
test4.cpp:34:21:错误:部分专用化"X<S*>
"声明为"朋友"
这根本不可能还是有一些解决方法?
我问的原因是我需要X<T*>
中的一个构造函数,它从任意X<S>
创建这个类(S
必须是T
的子类型)。
代码如下所示:
template <class T> class X<T*>{
T* t;
template<class S>
X(X<S> x) : t(&(x.t)) {} //Error, x.t is private
}
现在,编译器抱怨,当然,x.t
在构造函数中不可见,因为它是私有的。这就是为什么我需要部分专业化的朋友类。
在C++中,您可以在四个级别上授予超出private
的访问权限。
- 完全
public
访问(参见PMR的答案) - 继承层次结构中的访问(
protected
,此处无关紧要) - 到基本模板
friend
(请参阅此答案) - 到非模板或完全专业化的
friend
(太弱,无法解决您的用例)
后两种友谊之间没有中间道路。
来自C++标准的§14.5.4:。
朋友声明不得声明部分专业化。
以下声明将允许您实现所需的内容。 它使您可以自由地从任何其他专业化访问模板的任何专业化,但仍然仅在X
内。 它比你要求的稍微宽松一些。
template<class T> class X
{
template<class Any> friend class X;
public:
...
};
我们可以定义一个受 X 中定义的密钥保护的getter
。
#include <type_traits>
template <class T> class X{
T t;
public:
struct Key {
template<typename S>
Key(const X<S>&) {
static_assert(std::is_pointer<S>::value, "Not a pointer");
}
};
const T& get(Key) const { return t; }
T& get(Key) { return t; }
};
template <class T> class X<T*> {
T* t;
public:
template<class S>
X(X<S>& x) : t(&(x.get(typename X<S>::Key(*this)))) {}
};
int main()
{
X<int> x1;
X<int*> x2(x1);
return 0;
}
这仍然有一些弱点。现在,每个拥有X<T*>
的人都可以使用 get
.但到现在为止,这已经如此混乱,以至于没有人愿意去意识到这一点。我会选择一个简单的公共获取者。
相关文章:
- C++模板来检查友元函数的存在
- 模板类无法识别友元运算符
- 模板化的类和友元函数
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- 未定义的类模板不会实例化以检查友元函数
- 模板类中的模板友元函数
- 类模板中文本运算符的友元声明
- 与参数匹配的友元模板函数实例化
- 以嵌套类为参数的友元模板声明
- 模板化类的嵌套类中的友元运算符
- 为什么模板函数不能是模板类的友元模板函数
- 为什么 Visual C++无法编译从私有嵌套类继承的友元模板
- 在友元模板专用化的声明中不允许使用Constexpr
- C++中的友元模板函数
- 来自多个类的友元模板函数
- 友元模板函数类定义
- Visual Studio 2010 中的友元模板类和 Lambda 函数
- 创建友元模板函数时出现意外错误
- 普通类中的友元模板函数