I have two structures:
S_BETHEL_SPEAKER_SERVICE_TALK_INFO
S_MEMORIAL_INFO
And, at the moment I have two distinct methods, as follows:
void CMeetingScheduleAssistantApp::UpdateBethelServiceTalkInfo(COleDateTime datSpecialEvent, const S_BETHEL_SPEAKER_SERVICE_TALK_INFO sBSSTI)
{
const CString strDateKey = datSpecialEvent.Format(_T("%Y-%m-%d"));
if (m_mapSpecialEvents.find(strDateKey) != m_mapSpecialEvents.end())
{
S_SPECIAL_EVENT sEvent = m_mapSpecialEvents[strDateKey];
sEvent.sBSSTI = sBSSTI;
m_mapSpecialEvents[strDateKey] = sEvent; // Update
SaveEventsList();
}
}
void CMeetingScheduleAssistantApp::UpdateMemorialInfo(COleDateTime datSpecialEvent, const S_MEMORIAL_INFO sMI)
{
const CString strDateKey = datSpecialEvent.Format(_T("%Y-%m-%d"));
if (m_mapSpecialEvents.find(strDateKey) != m_mapSpecialEvents.end())
{
S_SPECIAL_EVENT sEvent = m_mapSpecialEvents[strDateKey];
sEvent.sMI = sMI;
m_mapSpecialEvents[strDateKey] = sEvent; // Update
SaveEventsList();
}
}
As you can see, they are virtually identical. Is it possible to consolidate these two functions into one with templates?
CodePudding user response:
That's possible by turning the function into a function template, and providing overloads for the assignment. The only requirement is that S_BETHEL_SPEAKER_SERVICE_TALK_INFO
and S_MEMORIAL_INFO
are different types (as opposed to type aliases for the same type).
The overloads for the assignments can be implemented on S_SPECIAL_EVENT
. The following implementation takes advantage of what is commonly known as hidden friends. Something like the following should do:
struct S_SPECIAL_EVENT {
// ...
private:
// Assignment overloads
friend inline void assign(S_SPECIAL_EVENT& event,
S_BETHEL_SPEAKER_SERVICE_TALK_INFO info) {
event.sBSSTI = info;
}
friend inline void assign(S_SPECIAL_EVENT& event,
S_MEMORIAL_INFO info) {
event.sMI = info;
}
};
With that in place you can then move on to implement the function template:
template<typename T>
void CMeetingScheduleAssistantApp::UpdateEventInfo(COleDateTime datSpecialEvent,
T info)
{
const CString strDateKey = datSpecialEvent.Format(_T("%Y-%m-%d"));
if (m_mapSpecialEvents.find(strDateKey) != m_mapSpecialEvents.end())
{
S_SPECIAL_EVENT sEvent = m_mapSpecialEvents[strDateKey];
assign(sEvent, info);
m_mapSpecialEvents[strDateKey] = sEvent; // Update
SaveEventsList();
}
}
Alternatively, since you're updating an existing value, you could just update it in-place, e.g.:
template<typename T>
void CMeetingScheduleAssistantApp::UpdateEventInfo(COleDateTime datSpecialEvent,
T info)
{
const CString strDateKey = datSpecialEvent.Format(_T("%Y-%m-%d"));
if (m_mapSpecialEvents.find(strDateKey) != m_mapSpecialEvents.end())
{
assign(m_mapSpecialEvents[strDateKey], info);
SaveEventsList();
}
}
If m_mapSpecialEvents
is a std::map
and you have access to a C 20 compiler you could further tighten the code taking advantage of contains()
:
template<typename T>
void CMeetingScheduleAssistantApp::UpdateEventInfo(COleDateTime datSpecialEvent,
T info)
{
const CString strDateKey = datSpecialEvent.Format(_T("%Y-%m-%d"));
if (m_mapSpecialEvents.contains(strDateKey))
{
assign(m_mapSpecialEvents[strDateKey], info);
SaveEventsList();
}
}