The usage of typename in C++

Preface

    When I was looking at the STL source code analysis recently, I encountered the usage of typename. I usually only came into contact with it when defining template parameters. Until I encountered this problem, I thoroughly searched for the usage of typename. Let's look at the next example:

typedef typename iterator_traits<_Iter>::value_type  value _type;

    We may be familiar with typedef, that is, to define an alias in the form: typedef+original type name+new type name; therefore, we can know that typename
iterator_traits<_Iter>::value_type is the type name; but what is confused is why it is necessary here Use the typename keyword?

Conventional usage of typename

        typename is a keyword frequently used in C++ class templates or function templates. At this time, the function is the same as class, except that the template parameters are defined; in the following example, the function implements generic exchange data, that is, exchanges the contents of two data, data The type is determined by _Tp.

template <typename _Tp>
inline void swap(_Tp& __a, _Tp& __b) 
{
  _Tp __tmp = __a;
  __a = __b;
  __b = __tmp;
}

The second usage of typename: modified type

    Before introducing the second usage, first understand some basic concepts,

Qualified and unqualified names

    A qualified name is a name that defines a namespace. Look at the following code, cout and endl are defined in the namespace std, std:: must be added to make them std::cout and std::endl, so they are called qualified names.

#include <iostream>

 int main()  
{
    std::cout << "Hello world!" << std::endl;
}

    If you use using namespace std in front of the main function; or using
std::cout; in the main function , then only use cout and endl when you use them. There is no more space in front of them to limit std::, so cout and endl is called an unqualified
name.

#include <iostream>
 using namespace std;
 int main()  
{
    //using std::cout;
	//using std::endl;
	cout << "Hello world!" << endl;
}

Dependent name and non-dependent name

   Dependent name (dependent name) refers to the name that depends on the template parameter, while non-dependent
name (non-dependent name) is the opposite, refers to the name that does not depend on the template parameter. Look at the following code:

template <class T>
class MyClass {
     int i;
     vector<int> vi;
     vector<int>::iterator vitr;
  
     T t;
     vector<T> vt;
      vector<T>::iterator viter;
 };

   Because int is a built-in type, the first three defined types are known when the template class is declared, and they are called non-dependent names. However, for the next three lines of definition, their types can only be known when the template is instantiated, because they all depend on the template parameter T. Then T,
vector<T>, vector<T>::iterator are called dependent names.

Class scope    

    When accessing the name in the class outside the class, you can use the class scope operator. There are usually three types of calls: static data members, static member functions, and nested types: Mydata::value,Mydata::function,Mydata::str ;

 class Mydata {
     static int value;
     static int function();
     typedef string str;
 };

Let's look at an example:

template <class T>
 void function()
 {
	T::iterator *iter;
	.....
 }

    When seeing the above example, we may have two ideas in our minds: First: T::iterator *iter; to achieve multiplication, iterator is a member of class T; Second: define a pointer, the type pointed to by the pointer is T::iterator;

    In this case, there will be objections. From the above introduction, we can know that iterator is a static data member of class T, a static member function or a nested type; if the keyword typename is not modified, the compiler may think that we want to implement multiplication; if we The original intention is that when you want to define a pointer, it needs to be modified by typename, that is, add the keyword typename in front of T::iterator;

template <class T>
 class myData()
 {
	typename T::iterator *iter;//定义一个指针
	typedef typename iterator_traits<_Iter>::value_type  value _type;//定义一个别名
	.....
 };

Typename usage rules

  The use of typename is prohibited in the following situations:

  1. Outside the template definition, that is, typename can only be used in the definition of the template
  2. Unqualified types, such as int, vector<int>, etc.
  3. In the base class list, such as template <class T> class C1: T::InnerType cannot add typename before T::InnerType
  4. In the initialization list of the constructor

       If the type is a qualified name that depends on the template parameter, then typename must be added before it (unless it is a list of base classes or in the list of initialized members of the class).

 

Undertake programming in Matlab, Python and C++, machine learning, computer vision theory implementation and guidance, both undergraduate and master's degrees, salted fish trading, professional answers please go to know, please contact QQ number 757160542 for details, if you are the one.

 

 

Guess you like

Origin blog.csdn.net/weixin_36670529/article/details/115053408