How to remove casts with templates in C++

  • 2020-04-02 03:13:20
  • OfStack

C++ is a strongly typed language compared to C, which means that it matches data types more strictly than C, which helps to avoid careless mistakes made by programmers during programming. Historically, keywords such as reinterpret_ cast, static_cast, etc. are still used for casts in C++, but the trend toward strong typing in languages requires us to use casts sparsely in our programming, and templates help us achieve this. Another benefit of using less casts is that the program is more maintainable.
Let's look at an example of how to reduce casts in a program through a template. Figure 1 illustrates, in simplified form, a partial implementation of a double-linked List (DLL) and a code snippet that USES a double-linked List.


class dll_t; 
 
class dll_node_t 
{ 
  friend class dll_t; 
 
public: 
  explicit dll_node_t (); 
 
  void data (void *_p_data) {p_data_ = _p_data;} 
  void *data () {return p_data_;} 
 
private: 
  dll_node_t *prev_; 
  dll_node_t *next_; 
  void *p_data_; 
}; 
 
class channel_t 
{ 
public: 
  channel_t () : node () 
  { 
    node_.data (reinterpret_cast <void *> (this)); 
  } 
 
private: 
  dll_node_t node_; 
}; 


Figure 1  

Among them, dll_node_t is the class encapsulation of the bidirectional linked list node. In addition to prev_ and next_, which are two member variables to hold the previous and next node Pointers, it also has a p_data_ to hold the node data. Since the meaning of the data held by the node is entirely up to the consumer of the linked list, the p_data_ type is defined as void* to hold data of any type. The data() function on lines 10 and 11 is used to set and get the value of the p_data_ variable, respectively.
 
Lines 19 to 29 in the figure illustrate a snippet of the channel_t class using the dll_node_t class. In the constructor of the channel_t class, the data() function needs to be cast to save this pointer to the node's p_data_ variable. It's not hard to imagine that when you get a value in p_data_ through the data() function, you also have to cast it into a pointer of type channel_t (this part of the code is not listed in the figure).
 
Figure 2 is a rewritten version using the template. It is believed that the reader can easily recognize the absence of casts.
 


template <typename T_NODE> class dll_t; 
 
template <typename T_DATA> class dll_node_t 
{ 
  friend class dll_t <dll_node_t <T_DATA> >; 
   
public: 
  explicit dll_node_t (); 
 
  void data (T_DATA *_p_data) {p_data_ = _p_data;} 
  T_DATA *data () {return p_data_;} 
   
private: 
  dll_node_t *prev_; 
  dll_node_t *next_; 
  T_DATA *p_data_; 
}; 
 
class channel_t 
{ 
public: 
  channel_t (): node_ () 
  { 
    node_.data (this); 
  } 
   
private: 
  dll_node_t <channel_t> node_; 
}; 

Figure 2

That's all for this article, and I hope it will help you to become familiar with removing casts using templates.


Related articles: