Home > Blockchain >  Can these two functions be turned into one by using templates?
Can these two functions be turned into one by using templates?

Time:10-20

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();
    }
}
  • Related