委派模板成员功能的良好设计
Good design for delegating template-member functionality
我很难为以下场景找到简单而优雅的设计。类 Worker
使用模板类Helper
来执行一些工作。在简单场景中,它看起来像这样:
template<typename T>
class Helper {
public:
void Help(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T m_data;
}
class SimpleWorker {
public:
SimpleWorker() : m_helper(SimpleData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
}
Helper<SimpleData> m_helper;
}
当模板参数更复杂并且与工作人员属于同一业务领域时,事情对我来说变得复杂。工作线程需要使用帮助程序,但它还需要在数据对象上调用一些帮助程序甚至不知道的方法(在此设计中)。像这样:
template<typename T>
class Helper {
public:
Helper(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T m_data;
}
class ComplexWorker {
public:
ComplexWorker() : m_helper(ComplexData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
m_helper.GetData().DoSomethingComplexNotConst(); // <-------------
}
Helper<ComplexData> m_helper;
}
明显的问题是我不能在结果上调用 not const 函数Data()
。使Data()
non-const 似乎是一个坏主意,因为Helper
也用于不同的上下文。我的目标是找到一种优雅的方式来使用其成员函数更改ComplexData
ComplexWorker
首先需要更改ComplexData
,以便Helper
可以继续处理更改后的数据。
编辑:更改Helper
构造以复制提供的数据以更好地类似于实际流程
我认为最好让Helper
只有静态函数,而不是维护状态(因为您在自己的代码中创建临时ComplexData()
ComplexWorker
)。通过引用或常量引用传递数据,具体取决于是否需要修改。
// primary template
template<typename T>
class Helper {
public:
static void help(T const& data) const {} // non-modifying
};
// specialization for ComplexData
template<>
class Helper<ComplexData> {
public:
static void help(ComplexData const& data) const { } // non-modifying
static void DoSomethingComplexNotConst(ComplexData& data) // modifying
{
// your implementation here
}
};
class ComplexWorker {
public:
ComplexWorker() : m_data(ComplexData()) {} // create new data
void DoWork()
{
Helper<ComplexData>::help(m_data);
Helper<ComplexData>::DoSomethingComplexNotConst(m_data); // <--- now no problem
}
private:
ComplexData m_data;
};
请注意,我为ComplexData
做了一个模板专用化。help()
中存在一些代码重复,但您可以轻松地将其提取到一个通用的非成员帮助程序函数中。
,这取决于Helper
实际在做什么。您的示例仅给出了一个构造函数和一个访问器,但我怀疑这就是它在实践中所做的一切。
您是否考虑过简单地使用继承?然后,您的Helper
模板将如下所示:
template<typename T>
class Helper : public T {
Helper(T data) : T(data) {}
void Help() {};
}
在这种情况下,您可以直接在"is-a"关系中使用Helper<ComplexData>
对象:
class ComplexWorker {
Helper<ComplexData> m_helper;
void DoWork()
{
m_helper.help();
m_helper.DoSomethingComplexNotConst();
}
}
为什么不参考 STL 中容器部分的实现。Data() 函数的重载可以在安全和优雅之间取得平衡。
template <typename T>
class Helper {
public:
Helper(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T& Data() {return m_data; }
private:
T m_data;
}
class ComplexWorker {
public:
ComplexWorker() : m_helper(ComplexData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
ComplexData &cd1 = m_helper.Data();
cd1.QuerySth();
const ComplexData &cd2 = m_helper.Data();
cd2.ModifySth();
}
private:
Helper<ComplexData> m_helper;
}
- 类模板的成员功能的定义在单独的TU中完全专业化
- 升压信号2将插槽传递到成员功能以断开连接
- 多次实现成员功能
- 如何定义可变参数类模板的成员模板功能
- 私有成员数据不可用于公共成员功能
- 好友功能 - 成员无法访问
- 如何启用友元类的友元功能直接在C++中访问其私有成员
- 无法从好友功能访问类的私有成员?"ostream"不是"std"的成员?
- C++从成员类型中扣除类型的功能模板?
- 如何避免大多数成员功能相同的代码重复
- 无法访问公共功能? 没有指定成员?
- C 成员功能
- =删除用户定义的成员功能,除了构造函数,分配运算符C 11
- C 朋友课程和朋友成员功能
- C 函数调用包装器包含类成员功能作为模板参数
- 共享库中静态功能成员的破坏顺序
- 可以使用仅功能成员属性进行回调界面
- 虚拟方法与std ::功能成员变量在性能方面
- 虚拟继承和功能成员
- 指向功能成员和非成员的指针