Learning notes on implicit type conversion in C + +

Time:2021-10-23

1 operator implicit type conversion

1.1 reference in STD:: ref source code_ Wrapper implicit type conversion

In the implementation of STD:: ref, there is the following code:

template<typename _Tp>
 class reference_wrapper
 : public _Reference_wrapper_base<typename remove_cv<_Tp>::type>
 {
  _Tp* _M_data;

 public:
  typedef _Tp type;

  reference_wrapper(_Tp& __indata) noexcept
  : _M_data(std::__addressof(__indata))
  { }

  reference_wrapper(_Tp&&) = delete;

  reference_wrapper(const reference_wrapper&) = default;

  reference_wrapper&
  operator=(const reference_wrapper&) = default;
  //Implicit type conversion of operator
  operator _Tp&() const noexcept
  { return this->get(); }

  _Tp&
  get() const noexcept
  { return *_M_data; }

  template<typename... _Args>
 typename result_of<_Tp&(_Args&&...)>::type
 operator()(_Args&&... __args) const
 {
  return __invoke(get(), std::forward<_Args>(__args)...);
 }
 };

Note the operator overload:


operator _Tp&() const noexcept
  { return this->get(); }

Is used for type conversion.

1.2 simple example – implement an example of converting class to int

#include <iostream>
/*
 *
 *Implicit type conversion of C + + operator
 *See the implementation of STD:: Ref
 */ 
void f(int a)
{
 std::cout << "a = " << a << std::endl;
}
class A{
 public:
 A(int a):num(a){}
 ~A() {}

 operator int()
 {
  return num;
 }
 int num;
};

int main()
{
 A a(1);
 std::cout << a + 1 << std::endl;
 f(a);
 return 0;
}

Of course, in addition to the implicit type conversion through the operator, it can also be implemented through the constructor in C + +.

2 constructor to implement implicit type conversion

It is mentioned in the book c + + primer

A constructor that can be called with a single argument defines a conversion from a formal parameter type to a class type

See the following example:

#include <iostream>
/*
 *
 *Implicit type conversion of C + + constructs
 *See the implementation of STD:: Ref
 */
class B{
 public:
 B(int a):num(a){}
 ~B() {}

 int num;
};

class A{
 public:
 A(int a):num(a){}
 A(B b):num(b.num){}
 ~A() {}

 int fun(A a)
 {
  std::cout << num + a.num << std::endl;
 }

 int num;
};

int main()
{
 B b(1);
 A a(2);
 //Implicit type conversion is implemented by constructor
 a.fun(b); // The output is 3
 return 0;
}

Special attention should be paid to the implicit conversion of the constructor only when a single argument is used. If a condition is not satisfied, it will not work.

3 use explicit keyword to avoid implicit conversion of constructor

Sometimes we don’t want implicit conversion. Unexpected implicit conversion may have unexpected results. Explicit keyword can prohibit such implicit conversion. Change the constructor of class A as follows


class A{
 public:
 A(int a):num(a){}
 explicit A(B b):num(b.num){}
 ~A() {}

 int fun(A a)
 {
  std::cout << num + a.num << std::endl;
 }

 int num;
};

When you run the program again, you will be prompted:

op2.cpp: In function ‘int main()’:
op2.cpp:29:12: error: no matching function for call to ‘A::fun(B&)’
a.fun(b);
^
op2.cpp:16:9: note: candidate: int A::fun(A)
int fun(A a)
^~~
op2.cpp:16:9: note: no known conversion for argument 1 from ‘B’ to ‘A’

At this time, the calling method is modified to:


int main()
{
 B b(1);
 A a(2);
 a.fun(A(b));
 return 0;
}

I can only lament the breadth and depth of C + + language. This article is only an entry-level summary of implicit conversion.

reference resources:

Learning and sorting of implicit class type conversion in C + + primer

The above is the details of the learning notes on implicit type conversion in C + +. For more information about implicit type conversion in C + +, please pay attention to other relevant articles of developeppaer!