如何为所有派生类型部分特化类模板?
我想部分专门化一个无法为基类和所有派生类更改的现有模板 (std::tr1::hash
)。 原因是我使用了奇怪的重复模板模式来实现多态性,并且哈希函数是在 CRTP 基类中实现的。 如果我只想部分专门化 CRTP 基类,那么很简单,我可以这样写:
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
但是这种专门化与实际的派生类不匹配,仅与 CRTPBase
匹配。 我想要的是一种为 Derived
编写部分特化的方法,当且仅当它派生自 CRTPBase
时。 我的伪代码是
namespace std { namespace tr1 {
template <typename Derived>
struct hash<typename boost::enable_if<std::tr1::is_base_of<CRTPBase<Derived>, Derived>,
Derived>::type>
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
...但这不起作用,因为编译器无法判断 enable_if
是 Derived
。 如果我可以更改 std::tr1::hash
,我只需添加另一个虚拟模板参数即可使用 boost::enable_if
,正如 enable_if 所建议的那样
文档,但这显然不是一个很好的解决方案。 有办法解决这个问题吗? 我是否必须在创建的每个 unordered_set
或 unordered_map
上指定自定义哈希模板,或者为每个派生类完全专门化 hash
?
I want to partially specialize an existing template that I cannot change (std::tr1::hash
) for a base class and all derived classes. The reason is that I'm using the curiously-recurring template pattern for polymorphism, and the hash function is implemented in the CRTP base class. If I only want to partially specialize for a the CRTP base class, then it's easy, I can just write:
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
But this specialization doesn't match actual derived classes, only CRTPBase<Derived>
. What I want is a way of writing a partial specialization for Derived
if and only if it derives from CRTPBase<Derived>
. My pseudo-code is
namespace std { namespace tr1 {
template <typename Derived>
struct hash<typename boost::enable_if<std::tr1::is_base_of<CRTPBase<Derived>, Derived>,
Derived>::type>
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
...but that doesn't work because the compiler can't tell that enable_if<condition, Derived>::type
is Derived
. If I could change std::tr1::hash
, I'd just add another dummy template parameter to use boost::enable_if
, as recommended by the enable_if
documentation, but that's obviously not a very good solution. Is there a way around this problem? Do I have to specify a custom hash template on every unordered_set
or unordered_map
I create, or fully specialize hash
for every derived class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下代码有两种变体。 您可以选择更适合您的。
There are two variants in the following code. You could choose more appropriated for you.
您应该创建自己的命名空间并定义从
std::tr1::hash< 继承的新结构
hash
,而不是修改std::tr1::hash
/code> 或专用于CRTPBase
。Instead of modifying
std::tr1::hash
you should make your own namespace and define there new structurehash
which inherited fromstd::tr1::hash
or is specialized forCRTPBase<Derived>
.C++20版本:
C++20 edition: