c++ - 减少模板策略困惑

标签 c++ templates

如果我有以下模板参数:

template <typename T_Key, typename T_Value, typename T_HashFunc, 
    typename T_ExtractKey, typename T_EqualKey, typename T_RehashClass, typename T_HashcodeClass>
  class Hashtable { /* ... */ };

其中T_RehashClassT_HashcodeClass是两个模板类,它们也接受T_Key、T_Value、T_HashFunc、T_ExtractKey和T_EqualKey。我希望这些类从 Hashtable 的 typedef 列表中获取类型(Hashtable 中的所有模板参数类型都是类型定义的)。

请注意,T_RehashClassT_HashcodeClass 也可以由用户创建(提供默认值),并且如果用户愿意,可以具有其他模板参数。

就目前情况而言,任何属于 T_RehashClass 的类都必须填写 T_Key、T_Value 等模板参数,我认为这是代码重复。我希望该类以某种方式了解 Hashtable ,以便它可以访问其 typedef 并通过创建自己的 typedef 自动推导 T_Key、T_Value 等类型。不幸的是,在这种情况下,我得到了循环依赖。

这类问题一般是如何解决的?

另请注意,我遵循 EASTL,其中 EASTL 使用多重继承来继承 T_RehashClassT_HashnodeClass,因此,Hashtable 具有更多功能模板参数。我想知道是否有解决方法(即不从两个策略继承并将它们作为模板参数,因为从策略继承会降低灵活性)。


我想到的一个解决方案是拥有一个模板结构,其中包含从 T_KeyT_EqualKey 的所有模板参数。 Hashtable 声明将是:

template <typename T_HashtableParams, typename T_RehashClass = default_rehash_class<T_HashtableParams>, typename T_HashcodeClass = default_hashnode_class<T_HashtableParams> >
  class Hashtable { /* ... */ };

然后,T_RehashClassT_HashcodeClass 可以采用默认值,从而消除代码重复。这种方法的问题是用户使用起来比较麻烦。

最佳答案

我不确定为哈希和重新哈希类指定不同的 T_Key 和 T_Value 类型是否非常有趣。如果我要解决这个问题,我会首先尝试为键/值设置策略。我的倾向是说也许应该有一个 ValuePolicy,而不是将其与 KeyPolicy 分组,但这既不在这里也不在那里。

namespace hash {
namespace detail {

    template<
            typename Key
            , typename Value
            , typename KeyGetter
            , typename KeyComparator>
        class KeyPolicy {
        public:
            typedef Key key_t;
            typedef Value value_t;
            typedef KeyGetter get_t;
            typedef KeyComparator compare_t;
        };

}} // hash detail

HashTable 无效,除非它具有与 rehast 相同的 KeyPolicy,所以不要给它一个。

namespace hash {
namespace detail {

    template<typename RehashPolicy>
        class HashTableImpl {
        public:
            typedef RehashPolicy rehash_p;
            typedef typename rehash_p::key_policy_t::key_t key_t;
            // typedef ...
        };

    // this doesn't have a specific name, its anything.
    template<typename KeyPolicy>
        class SomeRehashPolicy {
        public:
            typedef KeyPolicy key_policy_t;
        };

}} // hash detail

显然,您可以在那里添加任何您想要的类型定义。如果我是代码审查中的坚持者,我可能会要求将 rehash_pkey_policy_t 等内容设为私有(private)。它们确实是实现细节。您试图保护的实际不变量是 key_t 等中的内容。

也许我超出了礼仪的合理范围,但我诚实的观点是,所有这些配置只对编写它的人感兴趣。不是你,也不是任何使用它的人。因此,我只会公开人们实际要使用的一两个 HashTable 配置。

namespace hash {

    struct stub {}; // sorry, I'm lazy

    template<typename Key, typename Value>
        class HashTable {
        private:
            typedef typename detail::KeyPolicy<Key, Value, stub, stub> key_p;
            typedef typename detail::SomeRehashPolicy<key_p> rehash_p;
            typedef typename detail::HashTableImpl<rehash_p> impl_t;
        public:
            typedef typename impl_t::key_t key_t;
        };

} // hash

int main(int argc, char ** argv) {
    hash::HashTable<int, double> hash_table;
    return 0;
}

很多细节没有明显填写,但你明白了。

关于c++ - 减少模板策略困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8845618/

相关文章:

c++ - 概念可以替换模板关键字的所有其他实例吗?

java - 使用反射生成的 Java 源代码

javascript - 是否可以将 Handlebars 模板编译为 html?

c++ - 如何从 cin 获取用户输入到 C++11 std::array

c++ - 填充我的 IBO 的最佳方法是什么?

c++ - 带有 CRTP 的转发构造函数

c++ - 如何使函数在 C++ 中接收任意大小的多维数组?

c++ - 简化可变参数模板 : Remove some specializations

c++ - 显示多个壳对象的属性表

ruby - Jekyll:_includes 和布局问题