From 103ed00861c874f31d87b7a0f2737f22650efea9 Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Sat, 21 Nov 2015 12:13:54 +0000 Subject: [PATCH] Move Message assertions to special cast operators. Don't use static_cast directly anymore, but use these operators. --- include/znc/Message.h | 35 ++++++++++++++++++++++------------- src/Client.cpp | 22 +++++++++++----------- src/IRCSock.cpp | 24 ++++++++++++------------ 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/include/znc/Message.h b/include/znc/Message.h index 155c34d9..d2e0bf93 100644 --- a/include/znc/Message.h +++ b/include/znc/Message.h @@ -102,6 +102,28 @@ public: CString ToString(unsigned int uFlags = IncludeAll) const; void Parse(CString sMessage); + // Implicit and explicit conversion to a subclass reference. + template + M& As() & { + static_assert(sizeof(M) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); + return static_cast(*this); + } + + template + const M& As() const & { + static_assert(sizeof(M) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); + return static_cast(*this); + } + + template + operator M&() & { + return As(); + } + template + operator const M&() const & { + return As(); + } + private: void InitTime(); void InitType(); @@ -126,14 +148,12 @@ public: CString GetTarget() const { return GetParam(0); } void SetTarget(const CString& sTarget) { SetParam(0, sTarget); } }; -static_assert(sizeof(CTargetMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CActionMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1).TrimPrefix_n("\001ACTION ").TrimSuffix_n("\001"); } void SetText(const CString& sText) { SetParam(1, "\001ACTION " + sText + "\001"); } }; -static_assert(sizeof(CActionMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CCTCPMessage : public CTargetMessage { public: @@ -141,20 +161,17 @@ public: CString GetText() const { return GetParam(1).TrimPrefix_n("\001").TrimSuffix_n("\001"); } void SetText(const CString& sText) { SetParam(1, "\001" + sText + "\001"); } }; -static_assert(sizeof(CCTCPMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CJoinMessage : public CTargetMessage { public: CString GetKey() const { return GetParam(1); } void SetKey(const CString& sKey) { SetParam(1, sKey); } }; -static_assert(sizeof(CJoinMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CModeMessage : public CTargetMessage { public: CString GetModes() const { return GetParams(1).TrimPrefix_n(":"); } }; -static_assert(sizeof(CModeMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CNickMessage : public CMessage { public: @@ -162,20 +179,17 @@ public: CString GetNewNick() const { return GetParam(0); } void SetNewNick(const CString& sNick) { SetParam(0, sNick); } }; -static_assert(sizeof(CNickMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CNoticeMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1); } void SetText(const CString& sText) { SetParam(1, sText); } }; -static_assert(sizeof(CNoticeMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CNumericMessage : public CMessage { public: unsigned int GetCode() const { return GetCommand().ToUInt(); } }; -static_assert(sizeof(CNumericMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CKickMessage : public CTargetMessage { public: @@ -184,34 +198,29 @@ public: CString GetReason() const { return GetParam(2); } void SetReason(const CString& sReason) { SetParam(2, sReason); } }; -static_assert(sizeof(CKickMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CPartMessage : public CTargetMessage { public: CString GetReason() const { return GetParam(1); } void SetReason(const CString& sReason) { SetParam(1, sReason); } }; -static_assert(sizeof(CPartMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CQuitMessage : public CMessage { public: CString GetReason() const { return GetParam(0); } void SetReason(const CString& sReason) { SetParam(0, sReason); } }; -static_assert(sizeof(CQuitMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CTextMessage : public CTargetMessage { public: CString GetText() const { return GetParam(1); } void SetText(const CString& sText) { SetParam(1, sText); } }; -static_assert(sizeof(CTextMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); class CTopicMessage : public CTargetMessage { public: CString GetTopic() const { return GetParam(1); } void SetTopic(const CString& sTopic) { SetParam(1, sTopic); } }; -static_assert(sizeof(CTopicMessage) == sizeof(CMessage), "No data members allowed in CMessage subclasses."); #endif // !ZNC_MESSAGE_H diff --git a/src/Client.cpp b/src/Client.cpp index 06aa5f39..1367ca79 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -173,22 +173,22 @@ void CClient::ReadLine(const CString& sData) { switch (Message.GetType()) { case CMessage::Type::Action: - bReturn = OnActionMessage(static_cast(Message)); + bReturn = OnActionMessage(Message); break; case CMessage::Type::CTCP: - bReturn = OnCTCPMessage(static_cast(Message)); + bReturn = OnCTCPMessage(Message); break; case CMessage::Type::Join: - bReturn = OnJoinMessage(static_cast(Message)); + bReturn = OnJoinMessage(Message); break; case CMessage::Type::Mode: - bReturn = OnModeMessage(static_cast(Message)); + bReturn = OnModeMessage(Message); break; case CMessage::Type::Notice: - bReturn = OnNoticeMessage(static_cast(Message)); + bReturn = OnNoticeMessage(Message); break; case CMessage::Type::Part: - bReturn = OnPartMessage(static_cast(Message)); + bReturn = OnPartMessage(Message); break; case CMessage::Type::Ping: bReturn = OnPingMessage(Message); @@ -197,13 +197,13 @@ void CClient::ReadLine(const CString& sData) { bReturn = OnPongMessage(Message); break; case CMessage::Type::Quit: - bReturn = OnQuitMessage(static_cast(Message)); + bReturn = OnQuitMessage(Message); break; case CMessage::Type::Text: - bReturn = OnTextMessage(static_cast(Message)); + bReturn = OnTextMessage(Message); break; case CMessage::Type::Topic: - bReturn = OnTopicMessage(static_cast(Message)); + bReturn = OnTopicMessage(Message); break; default: bReturn = OnOtherMessage(Message); @@ -479,7 +479,7 @@ bool CClient::PutClient(const CMessage& Message) const CIRCSock* pIRCSock = GetIRCSock(); if (pIRCSock) { if (Msg.GetType() == CMessage::Type::Numeric) { - unsigned int uCode = static_cast(Msg).GetCode(); + unsigned int uCode = Msg.As().GetCode(); if (uCode == 352) { // RPL_WHOREPLY if (!m_bNamesx && pIRCSock->HasNamesx()) { @@ -524,7 +524,7 @@ bool CClient::PutClient(const CMessage& Message) } } else if (Msg.GetType() == CMessage::Type::Join) { if (!m_bExtendedJoin && pIRCSock->HasExtendedJoin()) { - Msg.SetParams({static_cast(Msg).GetTarget()}); + Msg.SetParams({Msg.As().GetTarget()}); } } } diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index b2baf6d5..26ed560f 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -168,7 +168,7 @@ void CIRCSock::ReadLine(const CString& sData) { bReturn = OnAccountMessage(Message); break; case CMessage::Type::Action: - bReturn = OnActionMessage(static_cast(Message)); + bReturn = OnActionMessage(Message); break; case CMessage::Type::Away: bReturn = OnAwayMessage(Message); @@ -177,7 +177,7 @@ void CIRCSock::ReadLine(const CString& sData) { bReturn = OnCapabilityMessage(Message); break; case CMessage::Type::CTCP: - bReturn = OnCTCPMessage(static_cast(Message)); + bReturn = OnCTCPMessage(Message); break; case CMessage::Type::Error: bReturn = OnErrorMessage(Message); @@ -186,25 +186,25 @@ void CIRCSock::ReadLine(const CString& sData) { bReturn = OnInviteMessage(Message); break; case CMessage::Type::Join: - bReturn = OnJoinMessage(static_cast(Message)); + bReturn = OnJoinMessage(Message); break; case CMessage::Type::Kick: - bReturn = OnKickMessage(static_cast(Message)); + bReturn = OnKickMessage(Message); break; case CMessage::Type::Mode: - bReturn = OnModeMessage(static_cast(Message)); + bReturn = OnModeMessage(Message); break; case CMessage::Type::Nick: - bReturn = OnNickMessage(static_cast(Message)); + bReturn = OnNickMessage(Message); break; case CMessage::Type::Notice: - bReturn = OnNoticeMessage(static_cast(Message)); + bReturn = OnNoticeMessage(Message); break; case CMessage::Type::Numeric: - bReturn = OnNumericMessage(static_cast(Message)); + bReturn = OnNumericMessage(Message); break; case CMessage::Type::Part: - bReturn = OnPartMessage(static_cast(Message)); + bReturn = OnPartMessage(Message); break; case CMessage::Type::Ping: bReturn = OnPingMessage(Message); @@ -213,13 +213,13 @@ void CIRCSock::ReadLine(const CString& sData) { bReturn = OnPongMessage(Message); break; case CMessage::Type::Quit: - bReturn = OnQuitMessage(static_cast(Message)); + bReturn = OnQuitMessage(Message); break; case CMessage::Type::Text: - bReturn = OnTextMessage(static_cast(Message)); + bReturn = OnTextMessage(Message); break; case CMessage::Type::Topic: - bReturn = OnTopicMessage(static_cast(Message)); + bReturn = OnTopicMessage(Message); break; case CMessage::Type::Wallops: bReturn = OnWallopsMessage(Message);