2011-06-15 75 views
6

我尝试使用(仅)STL创建BidirectionalMap类(不,boost不是一个选项)。我有99%的工作方式符合我的要求,但我真的无法弄清楚如何强制模板需要两种不同的类型,以便可以正确覆盖operator []。像...执行不同的C++模板参数

template < class KeyType, class ValueType > 
class BidirectionalMap 
{ 
    public: 

    ... 

    const ValueType& operator[](const KeyType& _k) { return(m_keyMap[ _k ]); } 
    const KeyType& operator[](const ValueType& _v) { return(m_valMap[ _v ]); } 

    private: 

    std::map<KeyType> m_keyMap; 
    std::map<ValueType> m_valueMap; 
}; 

main() 
{ 
    BidirectionalMap< Foo, Foo > fooMap; // won't work, ambiguous. 
    BidirectionalMap< Foo, Bar > fooBarMap; // does work. 
} 

想法? -R

+1

C++不会为你处理这个开箱即用的问题吗?既然你的'operator' []'会很好,我猜如果'KeyType'和'ValueType'相等,编译就会失败。 – larsmoa 2011-06-15 12:25:20

+0

你可以看一下'boost :: multi_index_container'的源代码来获得我想的一些提示。如果不符合许可证要求,您不能合法地复制代码,但您至少可以看到他们是如何做到的。 – 2011-06-15 12:26:00

+1

它已经需要不同的类型。为这两个参数提供相同的类型将尝试创建同一个方法'operator []'的两个不同版本,从而无法编译。你还想做什么? – Xion 2011-06-15 12:26:59

回答

15

只需添加以下部分特:

template <typename T> 
class BidirectionalMap<T, T>; 

这将情况下,编译来实例化没有定义(因为上述只声明)的模板和吊环如果用户试图传递与两个模板参数相同的类型。

+3

请务必在该声明下方提供有用的评论,向用户解释他们做错了什么。这实质上是他们的错误信息。 – 2011-06-15 12:26:39

+1

或者可能是一个带有static_assert的实现。 – juanchopanza 2011-06-15 12:37:02

+0

是的,把一个基本的构造函数与'false'的静态断言和一个合适的错误信息... – 2011-06-15 12:43:18

6

当然真正的问题是:为什么这样的任意限制?

我认为完全正常的拥有与键和值相同的类型,所以不是提供一个模糊的运算符重载,也许可以简单地提供两种不同的方法?

ValueType const& by_key(KeyType const&) const; 
KeyType const& by_value(ValueType const&) const; 

并且完成它。

编辑:继@Georg Fritzsche也此言:)

记住,超载的最重要的规则之一是,所有重载应该有相同的基本含义。

+0

我更喜欢一个类似于这样的解决方案 - 它不仅限制性较少,而且在阅读/调试(“等待,那个临时类型是什么?”)。 – 2011-06-15 13:39:11

+1

@Georg:的确,我已经编辑了答案,以便将其明确。所有重载应该具有相同的含义/执行(大致)相同的操作,否则读者很难理解正在发生的事情。 – 2011-06-15 14:19:36