2013-08-16 4 views
5

Ich habe eine Template-Funktion:Was ist falsch an einer flüchtigen Typableitung in Vorlagenfunktionen?

template <typename T> 
inline void Acquire_Store(volatile T* ptr, T value) { 
    // ... 
} 

Wenn ich versuche, es so zu berufen:

volatile Node* node; 
Acquire_Store(&node, static_cast<Node*>(nullptr)); 

Die beiden g ++, Klirren ++ Compiler sagen, so etwas wie folgt aus:

abgeleitet widersprüchliche Typen für Parameter 'T' ('flüchtige Liste :: Knoten *' vs. 'Liste :: Knoten *')

Wie kann diese Vorlagenfunktion korrekt aufgerufen werden?

Aktualisierung.

Jetzt bin ich nicht sicher über node 's Typ - vielleicht sollte ich es zu Node* volatile node; ändern?

Ich möchte die Variable node flüchtig sein, aber nicht das spitze Objekt.

+2

@ abyss.7 tun 'static_cast' Sie zwingen Compiler zu denken, dass' T' ist ein zwei verschiedene Arten zur gleichen Zeit :) - es wird wahrscheinlich auf einem Quantencomputer der 2113 Jahr möglich sein, aber nicht heutzutage :) – zaufi

+0

@zaufi vielleicht ist 'static_cast' eine falsche Sache - aber ich weiß nicht, wie man einen richtigen Anruf macht - darum geht es in der Frage. –

+0

was genau willst du? Natürlich müssen Sie entweder die Signatur oder eine Call-Site ändern. – zaufi

Antwort

1

Die Substitution und Deduktion ist nicht lexikalisch wie mit einem Makro. volatile T* wird nicht volatile Node** sondern volatile Node* volatile* werden. Das zweite volatile kommt von der Vorlage. Das macht T gleich volatile Node* für den ersten Parameter.

Versuchen Sie, sich von den volatilen immer am Anfang zu halten, aber setzen Sie es qhere es gehört nach dem tatsächlichen Typ. Ein flüchtiger Zeiger hat das flüchtige nach dem Stern, nicht davor.

0

Compiler Sie tatsächlich über Ihr Problem klar genug gesagt: Sie können T nicht verschiedene Typen gleichzeitig sein (Instanziierung). Das liegt daran, dass Sie den zweiten Parameter falsch darstellen. zum Beispiel können Sie „reparieren“ es dieses mag:

// kate: hl C++11; 
#include <iostream> 

struct Node {}; 

template <typename T> 
inline void Acquire_Store(volatile T* ptr, T value) 
{ 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

int main() 
{ 
    volatile Node* node; 
    Acquire_Store(&node, static_cast<volatile Node*>(nullptr)); 
    return 0; 
} 

dann Ausgabe

void Acquire_Store(volatile T*, T) [with T = volatile Node*] 

sein wird, aber ich verstehe immer noch nicht, was Sie erreichen wollen ...

+0

Ich habe die Frage aktualisiert. Vielleicht wirst du ein besseres Verständnis bekommen. –

0

Es scheint, dass das Problem darin liegt, dass der volatile Qualifier an welchen Typ auch immer gebunden ist.

template <typename T> 
inline void Acquire_Store(volatile T* ptr, T value) 

Also, wenn T = Node * für die oben, es ist die Zeiger Knoten, der flüchtig ist und nicht der Knoten selbst. Um das auf ein Objekt gerichtete flüchtige Objekt zu qualifizieren, muss es Teil von T sein. Dies stellt ein Problem dar, weil Ihr zweiter Parameter nicht-flüchtig ist - T kann nicht gleichzeitig flüchtig und nicht-flüchtig sein.

Was Sie tun können, ist T = volatile Node * zu machen und dann entfernen, dass die flüchtigen Qualifier aus dem zweiten Argument type_traits mit:

template <typename T> 
inline void Acquire_Store(T *ptr, typename std::remove_volatile<T>::type value); 

Hinweis all dies auch zu konst Qualifier gilt. Ideone demos this for const qualifier.