2016-03-30 3 views
-1

ich eine Template-Klasse geschrieben habeWie eine Funktion Signatur für eine Methode in einer Template-Klasse typedef wobei die Parameter ein generischer Typ ist

template<typename T, typename U> 
class ANotifier : public ACancelable 
{ 
public: 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, std::function<void(T&)> fn) = 0; 
    virtual void Notify(U msgType, T& value) = 0; 
}; 

template<typename T, typename U> 
class ASingleNotifier : public ANotifier<T, U> 
{ 
... 
} 

template<typename T, typename U> 
class AMultiNotifier : public ANotifier<T, U> 
{ 
... 
} 

Die Basisklasse eine Funktion Signatur im Lambda liefert. Ich muss die Funktionssignatur immer neu definieren, wenn ich die Funktion implementiere oder eine Stapelvariable der spezifischen Funktionssignatur machen möchte.

Ich habe mich gefragt, ob es einen Weg gibt, eine typedef

So etwas wie diese

template<typename T, typename U> 
class ANotifier : public ACancelable 
{ 
public: 
    typedef std::function<void(T&)> NotificationFn 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, NotificationFn fn) = 0; 
    virtual void Notify(U msgType, T& value) = 0; 
}; 

template<typename T, typename U> 
class ASingleNotifier : public ANotifier<T, U> 
{ 
... 
    virtual std::weak_ptr<ACancelableToke> RegisterNotification(U msgType, NotificationFn fn); 
} 

template<typename T, typename U> 
class AMultiNotifier : public ANotifier<T, U> 
{ 
... 
    virtual std::weak_ptr<ACancelableToke> RegisterNotification(U msgType, NotificationFn fn); 
} 

Habe ich eine typedef in jeder Vorlage Unterklasse deklarieren müssen zu erstellen. Wenn ich tatsächlich eine Stapelvariable zu einer Funktion eines bestimmten Typs erstelle, würde ich auch das Fn deklarieren. z.B. NotificationFn<uint32_t> fn;

habe ich, was ich habe oben und ich diesen Fehler:

/Users/kartik/Projects/pancam/hardware/neolib/inc/ANotifier.h:36:76: error: unknown type name 'NotificationFnOld' virtual std::weak_ptr RegisterNotification(U msgType, NotificationFnOld fn)

wo NotificationFnOld die gleiche wie NotificationFn ist

Was will ich tun in der Lage, die Funktion Signatur in einem sich ändern place (dh add/rem params) und an den typedef gebunden haben. Es macht mir nichts aus, neue typedefs in jeder Unterklasse zu deklarieren, solange ich nur einen Platz habe, um die Signatur zu ändern (natürlich muss ich die Funktionsimplementierungen ändern, aber ich möchte vermeiden, Zwischenvariablen und Zeug ändern zu müssen).

EDIT

Ich veränderte die typedef zu einem using und bekam noch einen ähnlichen Fehler. Das ist, was ich früher ... Statt typedef std::function<void(T&)> NotificationFn; I using NotificationFnOld = std::function<void(T&)>; verwendet

Und das ist der Fehler, den ich bekam.

/Users/kartik/Projects/pancam/hardware/neolib/inc/ANotifier.h:36:76: error: unknown type name 'NotificationFnOld' virtual std::weak_ptr RegisterNotification(U msgType, NotificationFnOld fn)

Der Fehler wird auf der Unterklasse berichtet ASingleNotifier im Prototyp der überschriebenen Funktion RegisterNotification. Es wird nicht beanstandet, wenn der Alias ​​in dem in ANotifier deklarierten Prototyp verwendet wird. Wie verwende ich den Alias ​​in meinen Unterklassen sauber?

HINWEIS: NotificationFnOld und NotificationFn werden in dieser Frage austauschbar verwendet, ich verwende tatsächlich nur NotificationFnOld in meinem Code.

EDIT

Incase Details benötigt werden, hier ist der Code von dem, was ich versuche. Es sollte keine Beziehung mit sein, aber wenn mehr Informationen benötigt werden, werde ich zur Verfügung stellen.

template<typename T, typename U> 
class ANotifier : public ACancelable 
{ 
public: 
    using NotificationFn = std::function<void(T&, std::weak_ptr<ACancelableToken>)>; 
    using NotificationFnOld = std::function<void(T&)>; 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, std::function<void(T&, std::shared_ptr<ACancelableToken>)> fn) = 0; 
    virtual void Notify(U msgType, T& value) = 0; 
}; 

template<typename T, typename U> 
class ASingleNotifier : public ANotifier<T, U> 
{ 
public: 
    virtual ~ASingleNotifier() 
    { } 

    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, std::function<void(T&, std::shared_ptr<ACancelableToken>)> fn) 
    { 
    std::weak_ptr<ACancelableToken> retval; 
    std::unique_lock <std::mutex> lk(m_mtx); 
    std::shared_ptr <ATypedCancelableToken<U>> tmp(std::make_shared<ATypedCancelableToken<U>>(*this, msgType)); 
    if(m_notifierMap.find(msgType) == m_notifierMap.end()) { 
     m_notifierMap[ msgType ] = std::make_pair(fn, tmp); 
     retval = tmp; 
    } 
    return retval; 
    } 

    virtual void CancelWith(std::shared_ptr<ACancelableToken> spBaseToken) const 
    { 
    try { 
     auto spToken = std::dynamic_pointer_cast<ATypedCancelableToken<U>>(spBaseToken); 
     std::unique_lock<std::mutex> lk(this->m_mtx); 
     m_notifierMap.erase(spToken->m_msgType); 
    } 
    catch (std::bad_cast exp) { } 
    } 

    virtual void Notify(U msgType, T& value) 
    { 
    m_mtx.lock(); 
    auto it = m_notifierMap.find(msgType); 
    if (it != m_notifierMap.end() && it->second.first) { 
     auto fn = it->second.first; 
     m_mtx.unlock(); 
     fn(value); 
    }else { 
     m_mtx.unlock(); 
    } 
    } 

protected: 
    mutable std::map <U, std::pair<std::function<void(T&, std::shared_ptr<ACancelableToken>)>, std::shared_ptr<ATypedCancelableToken<U>>>> m_notifierMap; 
    mutable std::mutex m_mtx; 
}; 

template<typename T, typename U> 
class AMultiNotifier : public ANotifier<T,U> 
{ 
protected: 
    class AmnCancellableToken : public ATypedCancelableToken<U> 
    { 
    public: 
    AmnCancellableToken(const ACancelable& cancellable, 
         U msgType, 
         typename std::list<std::pair<std::function<void(T&, std::shared_ptr<ACancelableToken>)>,std::shared_ptr<AmnCancellableToken>>>::iterator it) : 
     ATypedCancelableToken<U>{ cancellable, msgType }, m_it{ it } { } 
    ~AmnCancellableToken() {} 
    const typename std::list<std::pair<std::function<void(T&, std::shared_ptr<ACancelableToken>)>,std::shared_ptr<AmnCancellableToken>>>::iterator m_it; 
    }; 

public: 
    ~AMultiNotifier() { } 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, std::function<void(T&, std::shared_ptr<ACancelableToken>)> fn) 
    { 
    std::weak_ptr<ACancelableToken> retval; 
    std::unique_lock <std::mutex> lk(m_mtx); 
    std::shared_ptr<AmnCancellableToken> token; 

    m_notifierMap[ msgType ].push_back(std::make_pair(fn, token)); 
    auto it = m_notifierMap[msgType].end(); 
    token = std::make_shared<AmnCancellableToken>(*this, msgType, --it ); 

    m_notifierMap[ msgType ].back().second = token; 
    retval = token; 
    return retval; 
    } 

    virtual void CancelWith(std::shared_ptr<ACancelableToken> spBaseToken) const 
    { 
    try { 
     auto spToken = std::dynamic_pointer_cast<AmnCancellableToken>(spBaseToken); 
     std::unique_lock<std::mutex> lk(this->m_mtx); 
     if (!m_notifierMap[ spToken->m_msgType ].empty()) { //If the list of handler is not empty 
     m_notifierMap[ spToken->m_msgType ].erase(spToken->m_it); //Delete the handler in list 
     if (m_notifierMap[ spToken->m_msgType ].empty()) //If the list is now empty 
      m_notifierMap.erase(spToken->m_msgType); // Delete the msgType Key element 
     } 
    } catch (std::bad_cast exp) { } 
    } 

    virtual void Notify(U msgType, T& value) 
    { 
    m_mtx.lock(); 
    auto anotherCopy = m_notifierMap; 
    m_mtx.unlock(); 
    typename std::map<U, std::list<std::pair<std::function<void(T&, std::shared_ptr<ACancelableToken>)>, std::shared_ptr<AmnCancellableToken>>>>::iterator ait = 
     anotherCopy.find(msgType); 

    if(ait != anotherCopy.end() && 
     !ait->second.empty()) { 
     for(auto ait2 = ait->second.begin(); ait2 != ait->second.end(); ait2++) 
     if(ait2->first) 
      ait2->first(value); 
    } 
    } 

protected: 
    mutable std::map <U, std::list<std::pair<std::function<void(T&, std::shared_ptr<ACancelableToken>)>,std::shared_ptr<AmnCancellableToken>>>> m_notifierMap; 
    mutable std::mutex m_mtx; 
}; 

Danke für die Hilfe/Anregungen

Kartik

+0

Ich sehe kein Lambda in bereitgestellten Code. – SergeyA

+0

Erhalten Sie Fehler, wenn Sie den typedef Weg versuchen? – aschepler

+0

Die C++ 11 'using'-Syntax wird deutlicher als der alte 'typedef'-Mechanismus gelesen, sollte stattdessen verwendet werden. – kfsone

Antwort

1

Sie müssen NotificationFn qualifizieren:

virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, typename ANotifier<T,U>::NotificationFn fn); 

Oder wenn Sie werden es mehrmals zu verwenden, fügen Sie ein mit Aussage:

innerhalb jeder abgeleiteten Klasse.

hier ist ein komplettes Beispiel:

#include <iostream> 
#include <functional> 
#include <memory> 

struct ACancelable {}; 
struct ACancelableToken {}; 

template<typename T, typename U> 
class ANotifier : public ACancelable 
{ 
public: 
    using NotificationFn = std::function<void(T&)>; 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, NotificationFn fn) = 0; 
    virtual void Notify(U msgType, T& value) = 0; 
}; 

template<typename T, typename U> 
class ASingleNotifier : public ANotifier<T, U> 
{ 
    virtual std::weak_ptr<ACancelableToken> RegisterNotification(U msgType, typename ANotifier<T,U>::NotificationFn fn); 
}; 

int main() { 
    // your code goes here 
    return 0; 
} 

http://ideone.com/sXVkvw

+0

Danke ... das hat funktioniert. –

Verwandte Themen