如何使用策略在类中添加额外的功能层
How to use a policy to add an additional layer of functionality in the class?
最近,我不得不设计一个建立在另一个模板类之上的类。 种类:
template<
typename T1,
template <class> class A,
..>
class B {
A<T1> a1;
// other members;
public:
bool insert(T1 const & value);
bool update(T1 const & value);
bool delete(T1 const & value);
bool contains(T1 const & value);
};
我最初的计划是只提供值语义,这个接口很好。最近提出了一个要求,我的任务是在现有功能之外提供键控查找。我正在寻找以干净的方式做到这一点的解决方案。
只是添加bool find(KeyType const & key, ValueType & value)似乎不正确。是否应该存在键控查找应该取决于用户将决定的某些策略 - 因此查找方法本身将根据策略存在。
如何最好地做到这一点?
有多种方法可以做到这一点,但我认为这可能对你有用。这个想法是你定义一个基类,你的类(B
)从中继承。基类是一个具有一个 bool 参数的类模板,根据此参数的值,它定义或不定义查找成员。作为模板参数传递的值取决于您为几种可能的A
类型定义的类型特征。
警告:模板元编程如下。
让我们从类型特征开始。我假设可能的A
类型(这是一个模板模板参数)是 vector
、 map
等:
template <template <typename ...> class Container>
struct EnableKeyFind
{
static int const value = false; // fallback
};
template <>
struct EnableKeyFind<std::map>
{
static int const value = true;
};
template <>
struct EnableKeyFind<std::unordered_map>
{
static int const value = true;
};
换句话说,上面指出,在A == std::map
或A == std::unordered_map
时应该定义一个find
成员。在所有其他情况下,非专用模板是固定的,为此value == false
,即没有find
成员。您可以添加其他专用化来扩展此原则。
接下来,让我们定义基类:
template <typename Container, bool Enable>
class Base
{
Container &d_cont; // Base-class should have access to the container
public:
Base(Container &cont): d_cont(cont) {}
template <typename KeyType, typename ValueType>
bool find(KeyType const &key, ValueType const &val);
/* An alternative implementation would be where you use
Container::key_type and Container::value_type and get rid of
the function-template. This would require the Container-class
to have STL-like semantics. Pick whichever you prefer. */
};
// Specialization for 'false': no implementation
template <typename Container>
class Base<Container, false>
{
public:
Base(Container &cont) {}
};
基类专用于Enable
模板非类型参数false
的情况。在这种情况下,它的实现几乎是微不足道的(除了仍然需要相同签名的构造函数)。
现在让我们看一下修改后的B
类(我保留了非描述性名称以接近问题):
template <template <typename ...> class A, typename ... Types>
class B: public Base<A<Types ...>, EnableKeyFind<A>::value>
{
typedef A<Types ...> AType;
typedef Base<AType, EnableKeyFind<A>::value> BaseType;
AType a1;
public:
B():
BaseType(a1) // provide the base with access to a1
{}
};
由于不同的容器类型(如 vector
和 map
)需要不同数量的模板参数,因此我通过使其成为可变参数模板来稍微概括类模板。它现在可以存储任何类型的容器。它继承自Base
,并使用类型特征EnableKeyFind<A>
来确定它是否应该继承Base<Container, true>
或(特化)Base<Container, false>
。
一个典型的用例:
int main()
{
B<vector, int> b1;
b1.find(1, 1); // error: has no member find
B<map, string, int> b2;
b2.find(1, 1);
}
我希望这有所帮助。无论如何,这是一个有趣的小练习。
此方法的一个可能的缺点可能是,如果用户希望find()
可用,则应专用于其特定容器的EnableKeyFind
类模板。我不知道这对您的用户的要求是否太多,但是如果您想隐藏详细信息,您可以随时为他们提供一个宏:
define ENABLE_KEYFIND(Container)
template <>
struct EnableKeyFind<Container>
{ static int const value = true; };
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 在大括号内添加语句会更改代码功能?
- 如何在数据库程序中添加"reduce the quantity of an item"功能?
- 如何在控制台应用程序中添加滚动功能以显示更大的输入
- C++ 添加编译器警告,以错误使用自定义打印/日志功能
- C++要在其中添加接口功能的类层次结构
- 在 C++ 中向多态树添加功能
- 如何将搜索功能添加到数组中
- 如何为内置类型添加成员功能,例如C 中的整数
- 疯狂(乘,添加,划分)哈希功能如何起作用
- 将功能参数添加到向量
- 使用指针在功能中的数组中添加/删除元素
- 将功能添加到默认复制构造函数中
- C 将类成员功能添加到地图中
- 如何将搜索功能添加到WXWIDGET C 中的TextCtrl
- 我应该如何将另一个类的方法的功能添加到我的当前类中?
- 为气泡排序功能添加计数器
- 无法为包装器功能添加完美的转发
- 当您下载其他库并将其功能添加到C ++程序中时,您是否能够在另一台PC上运行您的软件(没有库)?
- 如何在gcc中保留命令行选项,但为某些功能添加更多优化标志