C++ Replaces Deleter of unique_ptr with lambda
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
Generally, when you need to give a template's Concept parameter, you pass in a type that implements the Concept just like the implementation of Code 1. For example, go_de implements the unique_ptr template parameter Deletor.
Today I want to try to pass in the type of lambda expression as a template parameter, but I find that it is not possible. The reason lies in
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 have used the default constructor of Deletor Concept. So the compilation failed. This is in
unique_ptr constructor page It's 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.
Imagine unique_ptr (pointer p, d1); if the constructor does not exist, then the Lambda type cannot be introduced as Concept.
summary
- To use the type of Lambda expression as Concept, decltype is derived by type.
- Lambda has no default constructor, copy assignment operator.
- When writing C++ library, if we use template and C oncept technology, we should consider adding C oncept object as constructor of parameter type so as not to restrict Lambda expression type to be imported as C oncept.
After all, the principle of C++ language design is to try not to restrict the programming methods of C++ language users.