在不知道其模板参数的情况下将类模板声明为朋友的最佳方法
Posted
技术标签:
【中文标题】在不知道其模板参数的情况下将类模板声明为朋友的最佳方法【英文标题】:Best approach to declare as friend a class template without knowing one its template arguments 【发布时间】:2019-02-11 12:07:09 【问题描述】:我偶然发现了一个场景,我正在尝试找出最干净的方法,如果有的话。
我有一个带有受保护构造函数的模板类,它需要由朋友模板类实例化。两者共享部分模板参数,但不是全部。这是我的问题的一个例子。
我想从有经验的程序员那里知道是否有其他可能的解决方案(我想没有,除了将构造函数公开),如果在这两者之间,我提出的一个比另一个更容易接受。 谢谢
解决方案 1- 我向具有受保护构造函数(元素类)的类提供“不必要的”模板参数。
template <typename Tp_>
class Engine_Type_X
;
template <typename Tp_>
class Engine_Type_Z
;
//Forward declaration
template <typename Tp_, template<typename> typename Eng_>
class Container;
//Eng_ is only required to declare the friend class
template <typename Tp_,template<typename> typename Eng_>
class Element
friend class Container<Tp_,Eng_>;
Tp_ tp_;
protected:
Element(Tp_ tp) : tp_tp //protected ctor!!!
;
template <typename Tp_, template<typename> typename Eng_>
class Container
using Element_tp = Element<Tp_,Eng_>;
using Engine_tp = Eng_<Tp_>;
std::vector<Element_tp> container_;
Engine_tp &engine_;
public:
Container(Engine_tp &engine) : container_,engine_engine
void install(Tp_ tp)
Element_tp elemtp;
container_.emplace_back(elem);
;
解决方案 2 - 我使用的方法类似于我在此处找到的方法 How to declare a templated struct/class as a friend?
template <typename Tp_>
class Engine_Type_X
;
template <typename Tp_>
class Engine_Type_Z
;
template <typename Tp_>
class Element
template<typename,template<typename>typename> friend class Container; //All templated classes are friend
Tp_ tp_;
protected:
Element(Tp_ tp) : tp_tp //protected ctor!!!
;
template <typename Tp_, template<typename> typename Eng_>
class Container
using Element_tp = Element<Tp_>;
using Engine_tp = Eng_<Tp_>;
std::vector<Element_tp> container_;
Engine_tp &engine_;
public:
Container(Engine_tp &engine) : container_,engine_engine
void install(Tp_ tp)
Element_tp elemtp;
container_.emplace_back(elem);
;
【问题讨论】:
两者有不同的含义。在第一个中只有Container<Tp_,Eng_>;
是Element<Tp_,Eng_>
的朋友在第二个中任何Container
是任何Element
的朋友,选择你需要的。
partial template specialization for friend classes?的可能重复
在您的情况下,另一种选择可能是将Element
声明为Container
的内部类(不确定这将如何适合您的整体设计)。
使用第二个。 Engine
逻辑上是 Container
的详细信息,因此将其放在 Element
的签名中是没有意义的。
【参考方案1】:
您仍有一些选择。
您可以将一个类设为内部类(称为嵌套类),这样会自动 将它与“外部”班级交朋友。见https://en.cppreference.com/w/cpp/language/nested_types
另一种方法是要求一个所谓的“令牌”作为参数 构造函数,这个token类型一般不带模板参数,那么就让这个token只能是 由其他类创建(可以是嵌套类型或友元类型)。
应 OP 的要求,这里概述了完成 2. 选项的一种方法:(使用 c++0x)
template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type ;
template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type ;
template <class T>
class create_token
public:
typedef T Type;
//copy of token not allowed !
create_token(const create_token &) = delete;
create_token& operator=(const create_token &) = delete;
//move is fine
create_token(create_token &&) = default;
create_token& operator=(create_token &&) = default;
friend class T;
private:
create_token();
;
template<class BlaBlaBla>
struct Element
template<class T>
Element(create_token<T> t)
static_assert(std::is_specialization<create_token<T>::Type, Container>::value, "Wrong type of token provided");
;
template<class Whatever>
struct Container
template<class T>
Element(create_token<T> t)
static_assert(std::is_specialization<create_token<T>::Type, Element>::value, "Wrong type of token provided");
;
【讨论】:
如果我将 Element 嵌套在 Container 中,如何在不明确将 Container 声明为朋友的情况下访问其受保护的构造函数?我不明白你的第二个建议。你能否提供一个简单的例子,不一定基于我自己的。谢谢。 @JacintoResende 我概述了如何执行第二个选项。它可能包含错误等,但我希望你觉得它有用。以上是关于在不知道其模板参数的情况下将类模板声明为朋友的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用画布的情况下将整个 div 数据转换为图像并将其保存到目录中?
如何在不使用全局存储的情况下将类对象从一个屏幕传递到另一个屏幕
在不知道编码类型的情况下将 NSData 转换为 NSString