Pregunta

Estoy haciendo una red neuronal y quería utilizar un hash_map para mantener las referencias de peso para las neuronas de salida para cada neurona:

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;
    }
};

Me doy cuenta que no puede utilizar el impulso :: shared_ptr como la clave de un stdext :: hash_map, así que lo que sería otra sugerencia? ¿Hay soluciones temporales o es la única opción de utilizar una clave diferente o tal vez cambiar a un std :: mapa? Gracias!

Aquí está el error:

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...
¿Fue útil?

Solución

Usted probablemente ha Neuron declarado en su archivo .h.

Así que el siguiente podría funcionar:

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;

El problema es que, probablemente, boost:shared_ptr no tiene ninguna función hash por defecto (lo que se vería así?), Por lo que sólo tiene que proporcionar una.

Otros consejos

También podría proporcionar una especialización de plantilla para el hash:

#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();
    }
};

Funciona perfectamente con unordered_set:

class Foo;
typedef boost::shared_ptr<Foo> FooPtr;
typedef std::tr1::unordered_set<FooPtr> FooSet;

A Neuron* "normal" debería funcionar como clave para el hash_map:

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

Si desea para buscar shared_ptr-neuronas puede utilizar shared_ptrs método get() para acceder al puntero sin formato:

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

weights.find(n.get());

Desde ya utiliza Boost, por qué no usar boost::unordered_map para la tabla hash? Se compila fuera de la caja con shared_ptr para la clave, aunque es mejor que ver cómo hacerlo correctamente ( Boost.Unordered )

A partir del código por encima de lo que es el error del compilador?

¿Ha tratado hacia adelante declare la neurona clase?

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();
    //...
};

un mapa estándar también debe estar bien en este caso, ¿cuál es su razón concreta para usar hash_map?

Me parece mediante la adición de una función hash_value () Puedo usar un shared_ptr como una llave en una stdext :: hash_map. A continuación comparo el uso de impulso :: unordered_map con 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>();
}

Problema con función hash se plantea para stdext::hash_set también. hash_value() solución con la que se declara es la mejor ya que se puede declarar sólo una vez en el archivo principal cabeceras.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top