2016-11-16 4 views
22

Dies ist eine Template-Funktion, die einen Zeiger (oder ein Zeiger wie Objekt) führt und eine Elementfunktion:Mitglied Funktionsaufruf auf Shared_ptr durch Mitglied Funktionszeiger in Vorlage

template <typename Ptr, typename MemberFunctor> 
int example(Ptr ptr, MemberFunctor func) 
{ 
    return (ptr->*func)(); 
} 

Wenn Werke, wenn sie mit gewöhnlichen Zeigern verwendet:

struct C 
{ 
    int getId() const { return 1; } 
}; 

C* c = new C; 
example(c, &C::getId); // Works fine 

Aber es funktioniert nicht mit Smart-Pointer:

std::shared_ptr<C> c2(new C); 
example(c2, &C::getId); 

Fehler Nachricht:

error: C2296: '->*' : illegal, left operand has type 'std::shared_ptr<C>' 

Warum? und wie man etwas macht, das mit beiden zusammenarbeitet?

+1

Verwandte: http://stackoverflow.com/questions/31851987/pointer-like-classes-and-the -Operator – Quentin

Antwort

19

std::shared_ptr unterstützt pointer-to-member access operator nicht (d. H. ->* und .*). Daher können wir Member-Funktionszeiger mit ->* nicht direkt darauf aufrufen. Sie können die aufrufende Syntax ändern, um operator* und operator.* zu verwenden, was sowohl für unformatierte Zeiger als auch für intelligente Zeiger funktioniert.

template <typename Ptr, typename MemberFunctor> 
int example(Ptr ptr, MemberFunctor func) 
{ 
    return ((*ptr).*func)(); 
} 

LIVE

7

std::shared_ptr nicht operator ->* nicht überlastet. Sie können eine Überlastung hinzufügen:

template <typename Ptr, typename MemberFunctor> 
int example(std::shared_ptr<Ptr> ptr, MemberFunctor func) 
{ 
    return (ptr.get()->*func)(); 
} 
12

std::shared_ptr hat kein operator->*. Sie haben zwei Möglichkeiten:

Sie könnten eine Überlastung schreiben, die ein std::shared_ptr (vielleicht eine für std::unique_ptr auch) nimmt:

template <typename T, typename MemberFunctor> 
int example(std::shared_ptr<T> ptr, MemberFunctor func) 
{ 
    return ((ptr.get())->*func)(); 
} 

Allerdings würde ich vorschlagen, nur machen example einen Verweis auf T nehmen und fordern func darauf. example muss nichts darüber wissen, wie der Zeiger gespeichert wird, so dass nicht alle diese zusätzlichen Überladungen erforderlich sein sollten.

template <typename T, typename MemberFunctor> 
int example(T&& t, MemberFunctor func) 
{ 
    return (std::forward<T>(t).*func)(); 
} 

Nun, wenn Sie einen std::shared_ptr<T> haben, würden Sie example wie nennen:

example(*my_shared_ptr, my_func); 
Verwandte Themen