【问题标题】:How Can I specialize a std map for multiple key types?如何为多种键类型专门化一个标准映射?
【发布时间】:2011-06-30 01:27:05
【问题描述】:

我有一个 std::map 的子类

template<class ValueT>
FancyKeyMap
    : public std::map<FancyKey,ValueT, FancyKey::Less>
{
     ...
public:
     inline iterator find(FancyKeyArg key)
     {
         return(std::map<FancyKey,ValueT,
                FancyKey::Less>::find(FancyKeyArg.makeKeyRef()));
     }  
};

这很好用,(不要问我为什么不想使用一些隐式转换,这会导致太多模棱两可的重载,在这种情况下完全转换也很昂贵:)

无论如何,如果上面的内容可以是 std::map 的任何一个专业化,那就太好了

std::map<FancyKey,ValueT> fancymap;

会做和

一样的事情
FancyKeyMap<ValueT> fancyMap;

可以做这种类型的专业化吗?


好的,只是尝试了部分专业化:

namespace std {

template<class ValT, class CompareT=FancyKey::Less, 
         class AllocT=allocator<pair<const FancyKey,ValT> > >
    class map<FancyKey, ValT, CompareT, AllocT>
{
     ....
};

}

我收到此错误:

“部分特化不允许使用默认参数”

但要使其像 std::map 一样,它需要具有“继承的”默认参数 并且 允许它们被覆盖。下一步可能吗?

我确实看到了关于使用可搜索模板常见问题解答的建议,这似乎是一个非常常见的问题;^>

【问题讨论】:

  • 你为什么有FancyKeyMap
  • 在 C++0x 中你可以说tempate &lt;typename T&gt; using FancyKeyMap = std::map&lt;FancyKey, T&gt;;
  • 我希望您知道从 STL 容器继承通常被认为是不好的做法,因为它们没有虚拟析构函数。如果你不向你的类添加数据成员,你可以侥幸逃脱,但最好改用组合。
  • @Alex:添加数据成员与它无关。 struct f : std::map&lt;int, int&gt; {}; std::map&lt;int, int&gt;* x = new f; delete x; 是未定义的行为。

标签: c++ templates specialization


【解决方案1】:

避免输入makeKeyRef()(在find 调用中)并同时更明确地说明意图似乎很麻烦。您是否考虑过只进行额外的输入并让未来的维护人员清楚您的意图?

此外,由于标准容器没有虚拟析构函数,除非您非公开继承,否则当某个容器被基类指针销毁时,您将面临未定义的行为。

【讨论】:

  • 由于子类只包含堆栈参数的内联转换,因此析构函数不是问题。主要目的是让人们可以编写代码,就好像它是一个 std::map 并让它选择正确的比较引用并根据密钥类型进行密钥引用转换,然后与标题一起改变集中定义行为(因式分解)而不必更改所有代码。或者,如果一个人同样切换键类型。我想要的是可以指定默认比较类型并覆盖一些方法的键类型的特化。
猜你喜欢
  • 2017-03-23
  • 1970-01-01
  • 2015-09-21
  • 2022-05-01
  • 2019-11-30
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多