2012-12-06 12 views
6

Ad esempio:Va bene rimuovere il qualificatore const quando la chiamata proviene dalla stessa funzione membro sovraccaricato della versione non-const?

struct B{}; 

struct A { 

const B& findB() const { /* some non trivial code */ } 

// B& findB() { /* the same non trivial code */ } 

B& findB() { 
     const A& a = *this; 
     const B& b = a.findB(); 
     return const_cast<B&>(b); 
    } 
}; 

Il fatto è che voglio evitare di ripetere la stessa logica all'interno della costante FINDB e funzione membro FINDB non costante.

+0

Ti sembra riferimenti molto. –

+0

Nessun punto nell'utilizzo di puntatori o copie se non necessario – dchhetri

risposta

7

Sì, si può lanciare l'oggetto da const, chiamare la versione const, poi gettato il risultato non const:

return const_cast<B&>(static_cast<const A*>(this)->findB()); 

gettando via const è sicuro solo quando l'oggetto in questione non è stato originariamente dichiarato const. Dato che ci si trova in una funzione membro non-const, è possibile sapere che questo è il caso, ma dipende dall'implementazione. Considerare:

class A { 
public: 

    A(int value) : value(value) {} 

    // Safe: const int -> const int& 
    const int& get() const { 
     return value; 
    } 

    // Clearly unsafe: const int -> int& 
    int& get() { 
     return const_cast<int&>(static_cast<const A*>(this)->get()); 
    } 

private: 
    const int value; 
}; 

In generale, le funzioni del mio membro sono brevi, quindi la ripetizione è tollerabile. A volte è possibile considerare l'implementazione in una funzione membro modello privata e chiamarla da entrambe le versioni.

+2

"Poiché si è in un metodo non const, si sa che questo è il caso." cosa intendi? Un metodo non-'convenst' può benissimo restituire un oggetto' const'. –

+2

se si dispone di una funzione di helper privata e non è una funzione const-member, come posso chiamarla dalla versione const senza rimuovere la costanza? Come potrei chiamare quella funzione di aiuto privato non costante dalla costante funzione di membro pubblico. Non si lamenterebbe ancora della sua costanza? – dchhetri

1

credo, che utilizzando gettato qui è ok, ma se si sicuramente vuole evitare di usarlo, è possibile utilizzare alcuni template magia:

struct B 
{ 
    B(const B&) 
    { 
     std::cout << "oops I copied"; 
    } 
    B(){} 
}; 

struct A { 
public: 
    A(){} 
    A(const A&){ std::cout << "a is copied:(\n";} 
    const B& findB() const { return getter(*this); }  
    B& findB() { return getter(*this); } 

private: 
    template <typename T, typename V> 
    struct same_const 
    { 
     typedef V& type; 
    }; 

    template <typename T, typename V> 
    struct same_const<const T, V> 
    { 
     typedef const V& type; 
    }; 

    template <typename T> 
    static typename same_const<T,B>::type getter(T& t) { return t.b;} 

    B b; 

}; 

int main() 
{ 
    A a; 
    const A a_const; 
    const B& b1 = a.findB(); 
    B& b2 = a.findB(); 

    const B& b3 = a_const.findB(); 
    //B& b4 = a_const.findB(); 
} 
+0

woah bel trucco, ma questo è eccessivo e renderebbe le cose molto peggiori secondo me. – dchhetri

+0

@ user814628, sono d'accordo, volevo solo farlo funzionare. – Lol4t0

Problemi correlati