The Deleter method of unique_ptr is replaced by lambda in C++

  • 2020-05-17 06:04:37
  • OfStack

code


#include <iostream>
#include <cstdlib>
#include <memory>
#include <string>
#include <functional>
using namespace std;
class go
{
public:
  go() {}
  ~go()
  {
    cout << "go die.\n";
  }
};
auto d = [] ( go * gp )
{
  delete gp;
  cout << "deletor done.\n";
};
class go_de
{
public:
  void operator() ( go* g )
  {
    d ( g );
  }
};
int main()
{
  {
    unique_ptr < go, go_de > b{ new go{} };//1
  }
  {
    //unique_ptr < go, decltype (d) > b{ new go{}}; complie error //2
    unique_ptr < go, decltype (d) > a{ new go{}, d };//3
  }
  {
    unique_ptr < go, function<void(go*) > > a{ new go{}, d };//4
    //i.e. unique_ptr < go, function<void(go*) > > a{ new go{}, [](go*gp) {delete gp;cout << "deletor done.\n"; }};
  }
  system ( "pause" );
  return 0;
}

describe

1, when you need to give a template Concept parameter, you will pass in a type that implements Concept like the implementation of code 1. For example, go_de implements the template parameter Deletor of unique_ptr.

Today I want to try 1 using the type of lambda expression passed in as a template parameter, but it doesn't work. The reason is that

c++14 draft n4269

5.1.2 Lambda expressions

20 The closure type associated with a lambda-expression has no default constructor and a deleted copy assignment operator. It has a defaulted copy constructor and a defaulted move constructor (12.8). [ Note: These special member functions are implicitly defined as usual, and might therefore be defined as deleted. end note ]

This means that the lambda expression has no default constructor, and operator= is also set to deleted. There is only one default copy constructor and move constructor. Obviously, the implementation of unique_ptr must use the default constructor of Deletor Concept. So it won't compile. This is in
The unique_ptr constructor page is clearly written.

2) Constructs a std::unique_ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter. Requires that Deleter is DefaultConstructible and that construction does not throw an exception.2) Constructs a std::unique_ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter. Requires that Deleter is DefaultConstructible and that construction does not throw an exception.

Consider unique_ptr(pointer p, d1); If the constructor does not exist, the Lambda type cannot be passed in as Concept.

conclusion

To use the type of the Lambda expression as Concept, use the type derivation keyword decltype The types of Lambda are not default constructor, copy assignment operator. When writing C++ library, if you are using templates and Concept techniques, you should consider adding the constructor of the type of Concept object as a parameter so as not to restrict the Lambda expression type to be passed in as Concept.

After all, the principle of C++ language design is to try not to limit how users of the C++ language can program.


Related articles: