2013-03-03 17 views
5

Sto creando la mia classe Filter personalizzata da utilizzare in boost :: filtered_graph. Il concetto WeightMap deve avere un costruttore predefinito, un costruttore di copie e un operatore di assegnazione.Assegnazione di uno std :: shared_ptr negli operatori di assegnazione

Ho creato la classe seguente, che ha un membro privato std :: shared_ptr. La mia domanda è come dovrei scrivere l'operatore del compito. Il costruttore di copie non era un problema, ma l'operatore di assegnazione non funziona.

class BFDMFilter 
{ 
private: 
const BGraph* m_battlemap; 
const std::shared_ptr<MoveAbility> m_mv_ab; 

public: 
BFDMFilter() : m_battlemap(nullptr), m_mv_ab() { } 
BFDMFilter(const BGraph* bmap, std::shared_ptr<MoveAbility> mv) : m_battlemap(bmap), m_mv_ab(mv) { } 

BFDMFilter(const BFDMFilter& filter) : m_battlemap(filter.m_battlemap), m_mv_ab(filter.m_mv_ab) { } 
BFDMFilter& operator=(const BFDMFilter& filter) 
{ 
    if(this != &filter) 
    { 
m_battlemap = filter.m_battlemap; 
m_mv_ab = filter.m_mv_ab; 
    } 

    return *this; 
} 

bool operator()(const Edge& edge) const 
{ 
    Tile::TileEdge path = (*m_battlemap)[edge]; 

    return m_mv_ab->CanMove(path.TerrainType()) > 0.0; 
} 

bool operator()(const Vertex& vertex) const 
{ 
    Tile tile = (*m_battlemap)[vertex]; 

    return m_mv_ab->CanMove(tile.TerrainType()) > 0.0; 
} 
}; 

che poi mi dà un errore di compilazione:

error: passing ‘const std::shared_ptr<momme::battle::MoveAbility>’ as ‘this’ argument of ‘std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp>&&) [with _Tp = momme::battle::MoveAbility, std::shared_ptr<_Tp> = std::shared_ptr<momme::battle::MoveAbility>]’ discards qualifiers [-fpermissive] 

capisco perché; l'operatore di assegnazione modifica il conteggio dei riferimenti di shared_ptr quando esegue l'assegnazione, in modo che possa tenere traccia del numero di riferimenti aperti esistenti. Ma allora, come scrivo l'operatore di assegnazione? std :: weak_ptr ha lo stesso comportamento, e se faccio il riferimento non-const, la libreria boost lamenta che la funzione è stata cancellata.

+2

Non sono sicuro del motivo per cui il puntatore deve essere const ... intendi 'std :: shared_ptr m_mv_ab', invece? Vuoi lo 'std :: shared_ptr' stesso const o l'oggetto a cui punta per essere const? –

+1

Non è possibile eseguire l'assegnazione con * qualsiasi * membro dati const '. Questo non è specifico per 'shared_ptr'. – juanchopanza

risposta

11

Non sembra esserci alcuna ragione dal codice per dichiarare m_mv_ab come

const std::shared_ptr<MoveAbility> m_mv_ab; 

che è la versione smart-pointer di:

MoveAbility * const m_mv_ab; 

(puntatore costante a non costante MoveAbility)

Se non si desidera modificare l'oggetto puntato a MoveAbility e si desidera che sia const, yo u dovrebbe fare:

std::shared_ptr<const MoveAbility> m_mv_ab; 

che è la versione smart-pointer di:

const MoveAbility * m_mv_ab; 

(puntatore non costante per costante MoveAbility)

Per rendere questo un po 'più intuitivo è possibile utilizzare const come suffisso sempre e sempre letto da destra a sinistra, tranne che std::shared_ptr<X> viene letto "puntatore (intelligente) su X":

std::shared_ptr<MoveAbility> const m_mv_ab; // const ptr to non-const MoveAbility 
MoveAbility * const m_mv_ab; // const ptr to non-const MoveAbility 

std::shared_ptr<MoveAbility const> m_mv_ab; // non-const ptr to const MoveAbility 
MoveAbility const * m_mv_ab; // non-const ptr to const MoveAbility 

ma la maggior parte delle persone usa const come prefisso ogni volta che è possibile, il che lo rende confuso.

+1

Che errore stupido; Non posso credere di averlo perso. Grazie per segnalarlo. – Brad

+0

@Brad succede sempre, non è così intuitivo –

Problemi correlati