在std::map中使用std::tm作为键

6
我想在std::map容器中使用std::tm()作为键。但是当我尝试编译它时,会出现许多(10个)错误。
例如:
1.
error C2784:'bool std :: operator <(const std :: basic_string <_ Elem,_ Traits,_ Alloc>&,const _Elem *)':无法推断出 'const std :: basic_string <_ Elem,_ Traits,_ Alloc>&' 的模板参数,来自 'const tm' c:\ program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional 125
2.
error C2784:'bool std :: operator <(const _Elem *,const std :: basic_string <_ Elem,_ Traits,_ Alloc>&)':无法推断出 'const _Elem *' 的模板参数,来自 'const tm' c:\ program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional 125
3.
error C2784:'bool std :: operator <(const std :: vector <_ Ty,_ Ax>&,const std :: vector <_ Ty,_ Ax>&)':无法推断出 'const std :: vector <_ Ty,_ Ax>&' 的模板参数,来自 'const tm' c:\ program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional 125
所有这些是否意味着我“只需”创建一个函数对象,比较两个std :: tm,因为没有为此定义标准比较?还是有其他技巧?(或者甚至对我来说是不可能的?^^)
代码:
#include <map>
#include <ctime>
#include <string>


int main()
{
    std::map<std::tm, std::string> mapItem;
    std::tm TM;

    mapItem[TM] = std::string("test");
    return 0;
};
4个回答

9

std::map 使用比较器来检查键是否已经存在。所以当你使用 std::tm 时,你也需要作为第三个参数提供一个比较器。

template < class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key,T> > > class map

所以一个解决方案就是使用函数对象(functor)(正如您已经猜到的那样):
struct tm_comparer
{
   bool operator () (const std::tm & t1, const std::tm & t2) const
   {           //^^ note this

        //compare t1 and t2, and return true/false
   }
};

std::map<std::tm, std::string, tm_comparer> mapItem;
                             //^^^^^^^^^^ pass the comparer!

或者定义一个自由函数(operator <),如下:

bool operator < (const std::tm & t1, const std::tm & t2)
{          // ^ note this. Now its less than operator

    //compare t1 and t2, and return true/false
};

std::map<std::tm, std::string> mapItem; //no need to pass any argument now!

如果我改用unordered_map,这会使它过时吗? - Juarrow
@Incubbus:不行。unordered_map 仍然需要它。因为两种类型的 map 都需要检查键。它们必须检查 唯一 的键。 - Nawaz
这个函数对象看起来足够吗?假设有人需要几秒钟来输入东西(因此tm_sec永远不应该相同)。 - Juarrow
@Incubbus:为什么 tm_sec 不能相同?01:30:0503:49:05 都有相同的 tm_sec。你可以将 tm 转换为秒数,然后仅比较秒数。或者如果你担心该值会超过数据类型(intlong long 或其他你使用的类型)的最大值,则可以将 tm 转换为小时和秒数。例如,5 天 4 小时 30 分钟 7 秒 将变为:(5 x 24 + 4) 小时和 30 x 60 + 7 秒。如果这样做,那么比较就很容易了。 - Nawaz
如果在检查STL代码后发现问题...似乎我的函数需要在最后一个位置返回false;至少在我做了一些测试之后它可以工作并且正常工作。 - Juarrow
显示剩余5条评论

2

是的,std::tm没有定义<运算符。


2

一个免费的函数就足够了,您不需要一个函数对象。


1
你可以使用免费的 < 运算符,但是你不能将任何自由函数作为 std::mapCompare 参数提供。模板定义为 template <class Key, class T, class Compare = less<Key>... - Andreas Brinck
@Andreas:你说得对。我把它和像for_each这样的情况混淆了,其中函数对象可以是任何可调用对象。 - Björn Pollex
1
其实我弄错了 ;) 请看这个链接:http://stackoverflow.com/questions/5989010/contradiction-in-c-standard - Andreas Brinck
@Andreas:发现得不错!谢谢分享。 - Björn Pollex

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接