我想实现两个简单的抽象类,如:
template <Hashable Key, typename Value>
class Dictionary {
.
.
.
};
这些类将为我提供在新词典类中进行部分模板特化的机会。
然而,我无法让他们工作。这是我的词典类的声明:
Equatable
问题是,密钥也应该是Equatable<T>
,因为可持续性应该需要它。
所以,我有两个问题:
我们可以重写Hashable
类没有模板参数吗? C ++是否有任何关键字引用该类的当前类型?
在我看来,Equatable
最好继承Hashable
班级。如何在var markers = L.markerClusterGroup({
polygonOptions: {
fillColor: '#1b2557',
color: '#1b2557',
weight: 0.5,
opacity: 1,
fillOpacity: 0.5
}
});
没有新的模板定义的情况下实现这一点(如果我的第一个问题回答是,那么这已经解决了)?
这里最好的面向对象方法是什么?使用模板参数的接口类看起来很俗气。
谢谢。
答案 0 :(得分:2)
你基本上寻找的是概念,你可以用它来编写:
template <class T>
concept bool Hashable()
{
return requires(T t, T u) {
{t.hashValue()} -> size_t;
{t == u} -> bool;
};
}
template <Hashable Key, class Value>
class Dictionary {
...
};
但这甚至不会出现在C ++ 17中。
在此之前,我们可以使用void_t
:
template <class...> using void_t = void;
template <class T, class = void>
struct Hashable : std::false_type { };
template <class T>
struct Hashable<T, void_t<
std::enable_if_t<std::is_same<std::declval<T&>().hashValue(), std::size_t>::value>,
decltype(std::declval<T&>() == std::declval<T&>())
>>
: std::true_type { };
template <class Key, class Value>
class Dictionary {
static_assert(Hashable<Key>::value, "Key must be Hashable<>");
...
};
请注意,在这两种情况下,我们都要求Key
类型具有此功能 - 我们不要求Key
继承虚拟。这样效率更高。无需虚拟调度。
这里最好的面向对象方法是什么?
不使用面向对象的方法。
答案 1 :(得分:1)
我相信
template <Hashable Key, typename Value>
实际上并没有按照您的预期行事。考虑:
template <int Key, typename Value> class x{};
现在,您可以实例化x<1, int>
和x<2, int>
,但这些不仅仅是不同的对象,而是不同的类型。因此,在您的情况下,您的Hashable
对象将成为该类型的一部分(因此它必须在编译期间生成,而不是在运行时生成)。
你最想要的是 - 就像在另一个答案中提到的Wojciech Frohmberg:
template <typename K, typename V>
class Dict {
...
static_assert(std::is_base_of<K, Hashable>::value, "Only Hashable can be the key);
}
或enable_if
或type_traits
中包含的其他模板魔法。
您正在寻找的是概念,甚至没有制作C ++ 17或类型类(在其他语言中可用,如Haskell或Scala)
如果您真的想在这里使用面向对象的方法,请选择以下内容:
template <typename Value>
class Dict {
Dict(std::shared_ptr<Hashable>, Value)
{}
}
但是,这不是典型的实现,所以我不推荐它