Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of member template functions in c++?

Tags:

c++

oop

Given a class with a member template function like this one:

template <typename t>
class complex
{
public:
    complex(t r, t im);
    template<typename u>
    complex(const complex<u>&);
private:
    //what would be the type of real and imaginary data members here.
}

I am confused about member template functions, please provide an example by which the need of member template functions becomes clear to me.
Also, tell me the use of member template functions in c++, what are the situations where we use member template functions?

like image 413
Zia ur Rahman Avatar asked Dec 09 '22 17:12

Zia ur Rahman


2 Answers

It gives you the ability to do conversions:

complex<int> ci;

complex<float> cf(ci);

So, if you have two types T1 and T2 and you can assign a T1 to a T2, this will make it possible to assign a complex<T1> to a complex<T2>.

As for the question in your code (what would be the type of real and imaginary data members here):

template <typename t>
class complex
{
...
private:
    t real_part;
    t imaginary_part;
};
like image 106
R Samuel Klatchko Avatar answered Dec 18 '22 15:12

R Samuel Klatchko


The most common valuable use for member template functions I come across in my day-to-day is to reduce code complexity by providing one templated function instead of many functions that do essentially the same thing.

For example, suppose you are working on a server that receives half a dozen related messages and saves the incoming data to half a dozen tables in a database. A straightforward implementation would be to implement 6 message handling functions (psudocode):

class MessageProcessor
{
  void OnMessage(const char* msg);
  void ProcessMessage100(Data100* data);
  void ProcessMessage101(Data101* data);
  void ProcessMessage102(Data102* data);
  void ProcessMessage103(Data103* data);
  void ProcessMessage104(Data104* data);
  void ProcessMessage105(Data105* data);
};

MessageProcessor::OnMessage(const char* msg)
{
  unsigned int * msgType = ((unsigned int*)msg);
  switch( *msgType )
  { 
    case 100 :
      ProcessMessage100((Data100*),sg);
      break;
    case 101 :
      ProcessMessage101((Data101*),sg);
      break;
    ::
  }
}

MessageProcessor::ProcessMessage100(Data100* data)
{
  Record100* record = GetRecord100(key);
  record->SetValue(xyz);
}

MessageProcessor::ProcessMessage101(Data101* data)
{
  Record101* record = GetRecord101(key);
  record->SetValue(xyz);
}

: :

There is an opportunity here to generalize the ProcessMessage() functions, since they do essentially the same thing:

class MessageProcessor
{
  OnMessage(const char* msg);

  template<class Record, class Data> void Process(Data* data);
};

template<class Record, class Data> 
void MessageProcessor::Process<Record,Data>(Data* data)
{
  Record* record = GetRecord(key);
  record->SetValue(xyz);
}

The GetRecord function can also be generalized, yielding a codebase with 2 functions where there used to be 12. This improves the code by virtue of it being simpler with fewer moving parts, simpler to understand and maintain.

like image 21
John Dibling Avatar answered Dec 18 '22 17:12

John Dibling