在Visual C ++和clang中使用C ++ 11 unordered_set [英] Using C++11 unordered_set in Visual C++ and clang

查看:268
本文介绍了在Visual C ++和clang中使用C ++ 11 unordered_set的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在跨平台C ++应用程序中使用std :: unordered_set。它在Windows下的Visual C ++中编译和工作像一个魅力,但在Mac OS X下的clang上生成一个致命的编译错误。



我想知道为什么会发生,

  > // 
// Clang build cmdline:
// $ clang ++ ./set.cpp -Wall -Werror -Wfatal-errors -std = c ++ 11 -stdlib = libc ++ -o set.out
//

#include< iostream>
#include< unordered_set>

struct Point {
int x,y;
Point(int x = 0,int y = 0){
this-> x = x;
this-> y = y;
}
bool operator ==(Point const& p)const {
return this-> x == p.x&& this-> y == p.y;
}
operator std :: size_t()const {
return std :: hash< int>()(x)^ std :: hash< int>
}
};

typedef std :: unordered_set< Point> points_set_t;

int main(){
Point point1(1,5);
Point point2(1,1);
Point point3(1,5);
points_set_t points;
points.insert(point1);
points.insert(point2);
points.insert(point3);
for(points_set_t :: const_iterator it = points.begin(); it!= points.end(); it ++){
std :: cout< it-> x< :<< it-> y< std :: endl;
}
}

Clang输出:

 在./set.cpp:6中包含的文件中:
在包含在/usr/bin/../lib/c++/v1/中的文件中iostream:38:
在/usr/bin/../lib/c++/v1/ios:216中包含的文件中:
在包含在/usr/bin/../lib/c++/中的文件中v1 / __ locale:15:
在/usr/bin/../lib/c++/v1/string:434包含的文件中:
在包含在/usr/bin/../lib/中的文件中c ++ / v1 / algorithm:591:
/usr/bin/../lib/c++/v1/type_traits:748:38:致命错误:未定义模板的隐式实例'std :: __ 1 :: hash< Point> ;'
:public integral_constant< bool,__is_empty(_Tp)> {};
^
/usr/bin/../lib/c++/v1/memory:1948:40:注意:在实例化模板类'std :: __ 1 :: is_empty< std :: __ 1: :hash< Point> >'
请求这里
bool = is_empty< _T2> :: value
^
/usr/bin/../lib/c++/v1/memory:1970:44 :注意:在实例化'__libcpp_compressed_pa​​ir_switch< unsigned
long,std :: __ 1 :: hash< Point>,false,false>'的默认参数时,
模板< class _T1,class _T2, unsigned = __libcpp_compressed_pa​​ir_switch< _T1,_T2> :: value>
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ usr / bin /../ lib / c ++ / v1 / memory:2354:15:注意:在实例化'__libcpp_compressed_pa​​ir_imp< unsigned long,

std :: __ 1 :: hash& ; >'required here
:private __libcpp_compressed_pa​​ir_imp< _T1,_T2>
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ usr / bin /../lib/c++/v1/__hash_table:527:55:注意:在实例化模板类'std :: __ 1 :: __ compressed_pa​​ir< unsigned long,
std :: __ 1 :: hash< Point> >'requested here
__compressed_pa​​ir< size_type,hasher> __p2_;
^
/usr/bin/../lib/c++/v1/unordered_set:330:13:note:在实例化模板类'std :: __ 1 :: __ hash_table< Point,
std :: __ 1 :: hash< Point>,std :: __ 1 :: equal_to< Point>,std :: __ 1 :: allocator< Point> >'requested here
__table __table_;
^
./set.cpp:28:18:注意:在实例化模板类'std :: __ 1 :: unordered_set< Point,std :: __ 1 :: hash< Point>,
std :: __ 1 :: equal_to< Point>,std :: __ 1 :: allocator< Point> >'requested here
points_set_t points;
^
/usr/bin/../lib/c++/v1/memory:3076:29:注意:模板在这里被声明
template< class _Tp> struct hash;
^
生成了1个错误。

UPD 使用@ mfontanini的建议工作实施: https://gist.github.com/vbo/6090142

解决方案

为了让 std :: unordered_set 使用 Point 类, std :: hash 专用化:

 命名空间std 
{
模板<>
struct hash< Point> {
size_t operator()(const Point& pt)const {
return std :: hash< int>(pt.x)^ std :: hash< int>(pt。 y)。
}
};
}

您也可以更改 std :: unordered_set 的第二个模板参数(它默认为 std :: hash< Point> ),表示返回所需哈希的函子类型。 >

看起来你试图通过用户定义的转换提供这个哈希实现到 size_t ,但是不行。它在VC中工作的事实是由它们的实现中的一些错误引起的。


I'am trying to use std::unordered_set in cross-platform C++ application. It compiles and works like a charm in Visual C++ under Windows, but generates a fatal compilation error on clang under Mac OS X.

I want to know why it happens and what is the right way to get this working.

Example code:

// 
// Clang build cmdline:
// $ clang++ ./set.cpp -Wall -Werror -Wfatal-errors -std=c++11 -stdlib=libc++ -o set.out
// 

#include <iostream>
#include <unordered_set>

struct Point {
    int x, y;
    Point(int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }
    bool operator==(Point const& p) const {
        return this->x == p.x && this->y == p.y;
    }
    operator std::size_t () const {
        return std::hash<int>()(x) ^ std::hash<int>()(y);
    }
};

typedef std::unordered_set<Point> points_set_t;

int main() {
    Point point1(1, 5);
    Point point2(1, 1);
    Point point3(1, 5);
    points_set_t points;
    points.insert(point1);
    points.insert(point2);
    points.insert(point3);
    for (points_set_t::const_iterator it = points.begin(); it != points.end(); it++) {
        std::cout << it->x << ":" << it->y << std::endl;
    }
}

Clang output:

In file included from ./set.cpp:6:
In file included from /usr/bin/../lib/c++/v1/iostream:38:
In file included from /usr/bin/../lib/c++/v1/ios:216:
In file included from /usr/bin/../lib/c++/v1/__locale:15:
In file included from /usr/bin/../lib/c++/v1/string:434:
In file included from /usr/bin/../lib/c++/v1/algorithm:591:
/usr/bin/../lib/c++/v1/type_traits:748:38: fatal error: implicit instantiation of undefined template 'std::__1::hash<Point>'
    : public integral_constant<bool, __is_empty(_Tp)> {};
                                     ^
/usr/bin/../lib/c++/v1/memory:1948:40: note: in instantiation of template class 'std::__1::is_empty<std::__1::hash<Point> >'
      requested here
                                bool = is_empty<_T2>::value
                                       ^
/usr/bin/../lib/c++/v1/memory:1970:44: note: in instantiation of default argument for '__libcpp_compressed_pair_switch<unsigned
      long, std::__1::hash<Point>, false, false>' required here
template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_switch<_T1, _T2>::value>
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/c++/v1/memory:2354:15: note: in instantiation of default argument for '__libcpp_compressed_pair_imp<unsigned long,

      std::__1::hash<Point> >' required here
    : private __libcpp_compressed_pair_imp<_T1, _T2>
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/c++/v1/__hash_table:527:55: note: in instantiation of template class 'std::__1::__compressed_pair<unsigned long,
      std::__1::hash<Point> >' requested here
    __compressed_pair<size_type, hasher>              __p2_;
                                                      ^
/usr/bin/../lib/c++/v1/unordered_set:330:13: note: in instantiation of template class 'std::__1::__hash_table<Point,
      std::__1::hash<Point>, std::__1::equal_to<Point>, std::__1::allocator<Point> >' requested here
    __table __table_;
            ^
./set.cpp:28:18: note: in instantiation of template class 'std::__1::unordered_set<Point, std::__1::hash<Point>,
      std::__1::equal_to<Point>, std::__1::allocator<Point> >' requested here
    points_set_t points;
                 ^
/usr/bin/../lib/c++/v1/memory:3076:29: note: template is declared here
template <class _Tp> struct hash;
                            ^
1 error generated.      

UPD Working implementation using @mfontanini's suggestion: https://gist.github.com/vbo/6090142.

解决方案

In order to make std::unordered_set work with your Point class, you can provide a std::hash specialization for it:

namespace std
{
template<>
struct hash<Point> {
    size_t operator()(const Point &pt) const {
        return std::hash<int>()(pt.x) ^ std::hash<int>()(pt.y);
    }
};
}

You could also change std::unordered_set's second template parameter(it defaults to std::hash<Point>), which indicates a functor type that returns the required hash.

It seems like you tried providing this hash implementation via a user defined conversion to size_t, but that won't work. The fact that it works in VC is caused by some bug in their implementation.

这篇关于在Visual C ++和clang中使用C ++ 11 unordered_set的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆