如何将模板模板参数传入的所有类型声明为MyStruct的友元?
让传入MyStruct的模板类型自动成为友元的两种实现方案
方案一:精准授权当前传入的子类型
如果只想让当前MyStruct实例所使用的SUB_TYPE模板特化类型成为友元(最安全的方式),只需将MyStruct中的友元声明替换为:
friend struct SUB_TYPE<MyStruct>;
修改后的完整代码:
template<typename MyStructType> struct OTHER_SUB_TYPE { OTHER_SUB_TYPE(MyStructType* p) { p->private_function(); } // 可访问MyStructType的其他私有成员 }; template<typename MyStructType> struct DEFAULT_SUB_TYPE { DEFAULT_SUB_TYPE(MyStructType* p) { p->private_function(); } // 可访问MyStructType的其他私有成员 }; template<template<typename> class SUB_TYPE = DEFAULT_SUB_TYPE> struct MyStruct { SUB_TYPE<MyStruct> Get() { return SUB_TYPE{this}; } // 仅授权当前使用的SUB_TYPE特化版本为友元 friend struct SUB_TYPE<MyStruct>; private: void private_function() {} }; int main() { MyStruct<> def; def.Get(); MyStruct<OTHER_SUB_TYPE> other; other.Get(); }
原理说明
SUB_TYPE<MyStruct>就是当前MyStruct实例对应的子类型特化(比如DEFAULT_SUB_TYPE<MyStruct<>>或OTHER_SUB_TYPE<MyStruct<OTHER_SUB_TYPE>>)- 这种写法只会让当前传入的子类型获得友元权限,不会开放给无关类型,安全性更高。
方案二:开放所有符合模板形式的子类型
如果需要所有满足template<typename> class形式的模板结构体都能成为MyStruct的友元(适合需要大量不同子类型的场景),可以使用模板模板参数的友元声明:
template<template<typename> class FriendSubType> friend struct FriendSubType;
修改后的完整代码:
template<typename MyStructType> struct OTHER_SUB_TYPE { OTHER_SUB_TYPE(MyStructType* p) { p->private_function(); } // 可访问MyStructType的其他私有成员 }; template<typename MyStructType> struct DEFAULT_SUB_TYPE { DEFAULT_SUB_TYPE(MyStructType* p) { p->private_function(); } // 可访问MyStructType的其他私有成员 }; template<template<typename> class SUB_TYPE = DEFAULT_SUB_TYPE> struct MyStruct { SUB_TYPE<MyStruct> Get() { return SUB_TYPE{this}; } // 授权所有单类型参数的模板结构体为友元 template<template<typename> class FriendSubType> friend struct FriendSubType; private: void private_function() {} }; int main() { MyStruct<> def; def.Get(); MyStruct<OTHER_SUB_TYPE> other; other.Get(); // 自定义子类型也能自动获得友元权限 template<typename T> struct CUSTOM_SUB_TYPE { CUSTOM_SUB_TYPE(T* p) { p->private_function(); } }; MyStruct<CUSTOM_SUB_TYPE> custom; custom.Get(); }
原理说明
- 这条友元声明表示:任何以单个类型为模板参数的结构体,都将成为当前MyStruct实例的友元。
- 无需手动逐个添加子类型的友元声明,新的子类型只要符合模板形式就能直接访问MyStruct的私有成员。
内容的提问来源于stack exchange,提问作者Wad
相关产品推荐
相关产品推荐

