Frage

Art einer zufälligen Frage ...

Was ich suche ist eine Möglichkeit, einen Gussvorgang zum Ausdruck bringen, die eine definierte Betreiber der Klasseninstanz verwendet von Ich bin Casting und erzeugt einen Fehler bei der Kompilierung, wenn es nicht eine definierte Cast-Operator für den Typ ist . So zum Beispiel, was ich suche ist so etwas wie:

template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
    return tValue.operator RESULT_TYPE();
}

// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );

// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );

Interessante Randnotiz:. Der obige Code stürzt die VS2005 C ++ Compiler und kompiliert nicht richtig in der VS2008 C ++ Compiler wegen dem, was ich vermute, ist ein Compiler Fehler, aber hoffentlich zeigt die Idee

Jeder weiß, von irgendeiner Weise diesen Effekt zu erzielen?

Edit: Weitere Gründe, zu erklären, warum Sie diese verwenden könnten. Sagen Sie bitte eine Wrapper-Klasse haben, die eine Art kapseln oder abstrakte soll, und du bist es zu dem eingekapselten Typ Gießen. Sie könnten verwenden static_cast <>, aber das könnte funktionieren, wenn man es wollte nicht (dh: der Compiler wählt ein Operator, der auf den Typ konvertieren darf Sie gefragt, wenn Sie einen Fehler wollte, weil die Betreiber nicht vorhanden ist).

Zwar ist es ein seltener Fall, aber es ist ärgerlich, dass ich nicht genau ausdrücken kann, was ich der Compiler soll in einer gekapselten Funktion tun ... daher die Frage hier.

War es hilfreich?

Lösung

Der Code geschrieben Sie arbeitet mit dem Cameau Compiler (die in der Regel ein guter Hinweis darauf, dass es gültig C ++).

Wie Sie wissen eine gültige Besetzung besteht aus nicht mehr als einem Benutzer definiert gegossen, so eine mögliche Lösung, die ich dachte, war das Hinzufügen einer weiteren Benutzers gegossen definiert durch einen neuen Typen in der Besetzung Vorlage definiert und ein statische assert , dass keine Stimmen aus dem neuen Typ des Ergebnistyp verfügbar ist (mit is_convertible ) steigern, jedoch ist dies nicht unterscheiden zwischen Cast-Operatoren und Gussbauer (ctor mit einem Argumente) und alows weitere Abgüsse zu (zB void* bool). Ich bin mir nicht sicher, ob eine Unterscheidung zwischen Cast-Operatoren machen und Gussbauer ist das die richtig Sache, aber das zu tun ist, was die Frage Staaten.

Nach ein paar Tagen brüten diese über sie mich treffen, können Sie einfach nehmen Sie die Adresse des Cast-Operator. Dies ist etwas leichter gesagt als aufgrund von C ++ 's haarigen Zeigern auf Member-Syntax durchgeführt (es hat mich Weg länger als erwartet, es zu erhalten rechts). Ich weiß nicht, ob dies auf VS2008 funktioniert, ich habe es nur auf Cameau.

template< typename Res, typename T>
Res operator_cast( const T& t )
{
    typedef Res (T::*cast_op_t)() const;
    cast_op_t cast_op = &T::operator Res;
    return (t.*cast_op)();
}

Edit: Ich habe eine Chance, es auf VS2005 und VS2008 zu testen. Meine Ergebnisse unterscheiden sich von den ursprünglichen senden.

  • Auf VS2008 die ursprüngliche Version (wie auch von mir) gut zu funktionieren scheint.
  • Auf VS2005 die ursprüngliche Version stürzt nur den Compiler, wenn sie von einem in Art gebaut Gießen nach (zB Gießen int int) einen Übersetzungsfehler, die jedoch nicht so schlecht zu mir scheint und meine Version in allen Fällen funktioniert scheint.

Andere Tipps

Mit einer Umwandlung Konstruktor explizit markiert ist, wie Sie würde von den Compiler verhindern, dass die Initialisierung Ihrer Wrapper-Klasse implizit konvertierte Typen ermöglicht.

Als Vorlage bezogenen Compiler-Fehlermeldungen sind in der Regel ein kompletter Schmerz zu entwirren, wenn Sie nichts dagegen haben, jede Umwandlung spezifizieren Sie den Compiler eine lehr Nachricht im Fall fehlschlagen emittieren bekommen können, indem sie zu einer Standardvorlage Definition. Dies nutzt die Tatsache, dass der Compiler nur Code in Templates zu erstellen versuchen, die tatsächlich aufgerufen wird.

#include <string>

// Class to trigger compiler warning   
class NO_OPERATOR_CONVERSION_AVAILABLE
{
private:
   NO_OPERATOR_CONVERSION_AVAILABLE(){};
};

// Default template definition to cause compiler error
template<typename T1, typename T2> T1 operator_cast(const T2&)
{
   NO_OPERATOR_CONVERSION_AVAILABLE a;
   return T1();
}

// Template specialisation
template<> std::string operator_cast(const std::string &x)
{
   return x;
}

klingt wie Sie Template-Spezialisierung wollen, so etwas wie dies tun würde:

/* general template */
template<typename T1, typename T2> T1 operator_cast(const T2 &x);

/* do this for each valid cast */
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }

EDIT:. Wie in einem anderen Beitrag erwähnt, können Sie etwas in der allgemeinen Version setzen Ihnen eine nützliche Fehlermeldung zu geben, wenn eine nicht unterstützte Besetzung durchgeführt wird

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top