2

我正在制作一个神经网络,并希望使用 hash_map 来为每个神经元的输出神经元保留权重参考:

class Neuron; //forward declaration was there (sorry I forgot to show it earlier)
typedef double WEIGHT;
typedef stdext::hash_map<boost::shared_ptr<Neuron>,WEIGHT> NeuronWeightMap;
class Neuron
{
private:
    NeuronWeightMap m_outputs;
    //...
public:

    Neuron();
    ~Neuron();
    //...
    WEIGHT GetWeight(const boost::shared_ptr<Neuron>& neuron) const
    {
        NeuronWeightMap::const_iterator itr = m_outputs.find(neuron);
        if( itr != m_outputs.end() )
        {
            return itr->second;
        }
        return 0.0f;
    }
};

我意识到我不能使用 boost::shared_ptr 作为 stdext::hash_map 的键,那么还有什么建议呢?是否有任何变通方法或者是使用不同键或切换到 std::map 的唯一选择?谢谢!

这是错误:

1>c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(61) : error C2440: 'type cast' : cannot convert from 'const boost::shared_ptr<T>' to 'size_t'
1>        with
1>        [
1>            T=Neuron
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(99) : see reference to function template instantiation 'size_t stdext::hash_value<_Kty>(const _Kty &)' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(98) : while compiling class template member function 'size_t stdext::hash_compare<_Kty,_Pr>::operator ()(const _Kty &) const'
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Pr=std::less<boost::shared_ptr<Neuron>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\hash_map(80) : see reference to class template instantiation 'stdext::hash_compare<_Kty,_Pr>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Pr=std::less<boost::shared_ptr<Neuron>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(119) : see reference to class template instantiation 'stdext::_Hmap_traits<_Kty,_Ty,_Tr,_Alloc,_Mfl>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Ty=common_ns::WEIGHT,
1>            _Tr=stdext::hash_compare<boost::shared_ptr<Neuron>,std::less<boost::shared_ptr<Neuron>>>,
1>            _Alloc=std::allocator<std::pair<const boost::shared_ptr<Neuron>,common_ns::WEIGHT>>,
1>            _Mfl=false
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\hash_map(90) : see reference to class template instantiation 'stdext::_Hash<_Traits>' being compiled
1>        with
1>        [
1>            _Traits=stdext::_Hmap_traits<boost::shared_ptr<Neuron>,common_ns::WEIGHT,stdext::hash_compare<boost::shared_ptr<Neuron>,std::less<boost::shared_ptr<Neuron>>>,std::allocator<std::pair<const boost::shared_ptr<Neuron>,common_ns::WEIGHT>>,false>
1>        ]
1>        FILE_PATH_REMOVED\neuralnet.h(21) : see reference to class template instantiation 'stdext::hash_map<_Kty,_Ty>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Ty=common_ns::WEIGHT
1>        ]
1>NeuralNet.cpp
1>c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(61) : error C2440: 'type cast' : cannot convert from 'const boost::shared_ptr<T>' to 'size_t'
1>        with
1>        [
1>            T=Neuron
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(99) : see reference to function template instantiation 'size_t stdext::hash_value<_Kty>(const _Kty &)' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(98) : while compiling class template member function 'size_t stdext::hash_compare<_Kty,_Pr>::operator ()(const _Kty &) const'
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Pr=std::less<boost::shared_ptr<Neuron>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\hash_map(80) : see reference to class template instantiation 'stdext::hash_compare<_Kty,_Pr>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Pr=std::less<boost::shared_ptr<Neuron>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\xhash(119) : see reference to class template instantiation 'stdext::_Hmap_traits<_Kty,_Ty,_Tr,_Alloc,_Mfl>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Ty=common_ns::WEIGHT,
1>            _Tr=stdext::hash_compare<boost::shared_ptr<Neuron>,std::less<boost::shared_ptr<Neuron>>>,
1>            _Alloc=std::allocator<std::pair<const boost::shared_ptr<Neuron>,common_ns::WEIGHT>>,
1>            _Mfl=false
1>        ]
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\hash_map(90) : see reference to class template instantiation 'stdext::_Hash<_Traits>' being compiled
1>        with
1>        [
1>            _Traits=stdext::_Hmap_traits<boost::shared_ptr<Neuron>,common_ns::WEIGHT,stdext::hash_compare<boost::shared_ptr<Neuron>,std::less<boost::shared_ptr<Neuron>>>,std::allocator<std::pair<const boost::shared_ptr<Neuron>,common_ns::WEIGHT>>,false>
1>        ]
1>        FILE_PATH_REMOVED\neuralnet.h(21) : see reference to class template instantiation 'stdext::hash_map<_Kty,_Ty>' being compiled
1>        with
1>        [
1>            _Kty=boost::shared_ptr<Neuron>,
1>            _Ty=common_ns::WEIGHT
1>        ]
1>Generating Code...
4

7 回答 7

11

您可能已Neuron在 .h 文件中声明。

所以下面可以工作:

struct hasher {
    size_t operator()(const boost::shared_ptr<Neuron>& n) { return (size_t)n.get(); }
};

typedef stdext::hash_map<boost::shared_ptr<Neuron>,WEIGHT,hasher> NeuronWeightMap;

问题可能是boost:shared_ptr没有默认的散列函数(看起来像什么?),所以你只需要提供一个。

于 2009-05-22T23:33:01.173 回答
8

您还可以为哈希提供模板特化:

#include <functional>
#include <boost/shared_ptr.hpp>

template<class T>
class std::tr1::hash<boost::shared_ptr<T>> {
public:
    size_t operator()(const boost::shared_ptr<T>& key) const {
        return (size_t)key.get();
    }
};

与 unordered_set 完美配合:

class Foo;
typedef boost::shared_ptr<Foo> FooPtr;
typedef std::tr1::unordered_set<FooPtr> FooSet;
于 2010-01-18T16:16:40.127 回答
3

“正常”Neuron*应该作为关键hash_map

typedef stdext::hash_map<Neuron*, WEIGHT> NeuronWeightMap;

如果要查找shared_ptr-Neurons,可以使用shared_ptrsget()方法访问原始指针:

NeuronWeightMap weights;
boost::shared_ptr<Neuron> n;

weights.find(n.get());
于 2009-05-22T23:37:42.367 回答
1

既然你已经使用了 Boost,为什么不使用boost::unordered_map哈希表呢?它使用 for 键编译开箱即用shared_ptr,但您最好检查如何正确执行 ( Boost.Unordered )

于 2009-05-23T00:01:23.503 回答
0

从上面的代码中编译器错误是什么?

您是否尝试过声明神经元类?

class Neuron; // class Neuron must be forward declared to be used

typedef double WEIGHT;
typedef stdext::hash_map<boost::shared_ptr<Neuron>,WEIGHT> NeuronWeightMap;


class Neuron
{
private:
    NeuronWeightMap m_outputs;
    //...
public:

    Neuron();
    ~Neuron();
    //...
};

在这种情况下,标准地图也应该没问题,您使用 hash_map 的具体原因是什么?

于 2009-05-22T23:22:37.013 回答
0

我发现通过添加 hash_value() 函数,我可以使用 shared_ptr 作为 stdext::hash_map 中的键。下面我比较使用 boost::unordered_map 和 std::hash_map

#include <boost/smart_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <hash_map>
#include <assert.h>

struct MyItem
{
    int i;
};
typedef boost::shared_ptr<const MyItem> MyItem_csptr;

struct MyExtra
{
    double d;
};

//Boost's unordered_map already knows how to hash shared_ptr
typedef boost::unordered_map<MyItem_csptr,MyExtra> MapMyItemToExtra;


//But for stdext::hash_map, we need to write this:
template<class T>
size_t hash_value(const boost::shared_ptr<T>& aSptr)
{
    return reinterpret_cast<size_t>( aSptr.get() );
};
typedef stdext::hash_map<MyItem_csptr,MyExtra> MapMyItemToExtra2;


template<class MAP>
void TryMapMyItemToExtra_T()
{
    MAP tMap;

    MyItem_csptr tItem1(new MyItem);
    MyItem_csptr tItem2(new MyItem);
    tMap[tItem1].d=1.0;
    tMap[tItem1].d=1.1;
    tMap[tItem2].d=2.0;

    assert( tMap[tItem1].d == 1.1 );
    assert( tMap[tItem2].d == 2.0 );
}

void TryMapMyItemToExtra()
{
    TryMapMyItemToExtra_T<MapMyItemToExtra>();
    TryMapMyItemToExtra_T<MapMyItemToExtra2>();
}
于 2010-01-05T13:01:54.213 回答
0

哈希函数的问题stdext::hash_set也随之而来。带有声明的解决方案hash_value()是最好的,因为您可以在主头文件中只声明一次。

于 2011-11-08T18:19:42.343 回答