如何在 C++11 中 return 包含自定义删除器的 std::unique_ptr?
How to return the std::unique_ptr containing custom deleter in C++11?
我的应用程序编译器最多只能支持 c++11
。
下面是我的项目和函数 get_conn()
returns std::unique_ptr
的代码片段,带有自定义删除器(删除器需要两个参数)。我正在为 return 类型使用 auto
关键字,但它给出了一个错误,就像 if is compiled with c++11
(compiles fine with c++14
)
error: ‘get_conn’ function uses ‘auto’ type specifier without trailing return type
演示示例代码:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
// Dummy definition of API calls
int* open_conn (int handle)
{
return new int;
}
void close_conn (int handle, int *conn)
{}
auto get_conn (int handle)
{
// API call
int* conn = open_conn (handle);
auto delete_conn = [](int *conn, int handle) {
// API call
close_conn (handle, conn);
delete conn;
};
auto delete_binded = std::bind (delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, decltype(delete_binded)> (conn, delete_binded);
}
int main()
{
int handle = 2; // suppose
auto c = get_conn (handle);
if (!c)
cout << "Unable to open connection\n";
return 0;
};
如何将 auto
关键字替换为 std::unique_ptr
的实际 return 类型以与 c++11
兼容代码?
我尝试使用以下 return 类型但失败了
std::unique_ptr<int, void(*)(int *,int)> get_conn(int handle)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
// ...
}
你的 lambda 被传递到 std::bind
,所以你得到另一个未命名的对象,你只知道它有 void (int*)
签名。
int
因为绑定了第二个参数,所以像void(*)(int *,int)
一样放在签名中是错误的。这个仿函数只接受指向 int 的指针。
使用std::function
:
std::unique_ptr<int, std::function<void(int*)>>
get_conn (int handle)
{
// API call
int* conn = open_conn (handle);
auto delete_conn = [](int *conn, int handle)
{
// API call
close_conn (handle, conn);
delete conn;
};
auto delete_binded = std::bind (delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, std::function<void(int*)> > (conn, delete_binded);
}
回到函子!
函数的 auto
return 类型是 c++14 特征。为了提供实际的 return 类型,您可以提供如下仿函数(如评论中提到的 @IgorTandetnik)。优点是,您不再需要 std::bind
。
(See online)
struct DeleteConn // functor which subsituts the lambda and `std::bind`
{
int _handle;
explicit DeleteConn(int handle): _handle{ handle } {}
void operator()(int* conn) const
{
// API call
close_conn(_handle, conn);
delete conn;
}
};
std::unique_ptr<int, DeleteConn> get_conn(int handle)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> now you can provide the actual type.
{
// API call
int* conn = open_conn(handle);
DeleteConn delete_conn{ handle };
return std::unique_ptr<int, DeleteConn>(conn, delete_conn);
}
或者,您可以将 lambda 函数 delete_conn
从 get_conn
函数中移出并使用 trailing return type which is a c++11 特性。
(See Online)
namespace inter {
auto delete_conn = [](int* conn, int handle)
{
// API call
close_conn(handle, conn);
delete conn;
};
}
auto get_conn(int handle)
->std::unique_ptr<int, decltype(std::bind(inter::delete_conn, std::placeholders::_1, handle))>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->Trailing return type
{
// API call
int* conn = open_conn(handle);
auto delete_binded = std::bind(inter::delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, decltype(delete_binded)>(conn, delete_binded);
}
我的应用程序编译器最多只能支持 c++11
。
下面是我的项目和函数 get_conn()
returns std::unique_ptr
的代码片段,带有自定义删除器(删除器需要两个参数)。我正在为 return 类型使用 auto
关键字,但它给出了一个错误,就像 if is compiled with c++11
(compiles fine with c++14
)
error: ‘get_conn’ function uses ‘auto’ type specifier without trailing return type
演示示例代码:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
// Dummy definition of API calls
int* open_conn (int handle)
{
return new int;
}
void close_conn (int handle, int *conn)
{}
auto get_conn (int handle)
{
// API call
int* conn = open_conn (handle);
auto delete_conn = [](int *conn, int handle) {
// API call
close_conn (handle, conn);
delete conn;
};
auto delete_binded = std::bind (delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, decltype(delete_binded)> (conn, delete_binded);
}
int main()
{
int handle = 2; // suppose
auto c = get_conn (handle);
if (!c)
cout << "Unable to open connection\n";
return 0;
};
如何将 auto
关键字替换为 std::unique_ptr
的实际 return 类型以与 c++11
兼容代码?
我尝试使用以下 return 类型但失败了
std::unique_ptr<int, void(*)(int *,int)> get_conn(int handle)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
// ...
}
你的 lambda 被传递到 std::bind
,所以你得到另一个未命名的对象,你只知道它有 void (int*)
签名。
int
因为绑定了第二个参数,所以像void(*)(int *,int)
一样放在签名中是错误的。这个仿函数只接受指向 int 的指针。
使用std::function
:
std::unique_ptr<int, std::function<void(int*)>>
get_conn (int handle)
{
// API call
int* conn = open_conn (handle);
auto delete_conn = [](int *conn, int handle)
{
// API call
close_conn (handle, conn);
delete conn;
};
auto delete_binded = std::bind (delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, std::function<void(int*)> > (conn, delete_binded);
}
回到函子!
函数的 auto
return 类型是 c++14 特征。为了提供实际的 return 类型,您可以提供如下仿函数(如评论中提到的 @IgorTandetnik)。优点是,您不再需要 std::bind
。
(See online)
struct DeleteConn // functor which subsituts the lambda and `std::bind`
{
int _handle;
explicit DeleteConn(int handle): _handle{ handle } {}
void operator()(int* conn) const
{
// API call
close_conn(_handle, conn);
delete conn;
}
};
std::unique_ptr<int, DeleteConn> get_conn(int handle)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> now you can provide the actual type.
{
// API call
int* conn = open_conn(handle);
DeleteConn delete_conn{ handle };
return std::unique_ptr<int, DeleteConn>(conn, delete_conn);
}
或者,您可以将 lambda 函数 delete_conn
从 get_conn
函数中移出并使用 trailing return type which is a c++11 特性。
(See Online)
namespace inter {
auto delete_conn = [](int* conn, int handle)
{
// API call
close_conn(handle, conn);
delete conn;
};
}
auto get_conn(int handle)
->std::unique_ptr<int, decltype(std::bind(inter::delete_conn, std::placeholders::_1, handle))>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->Trailing return type
{
// API call
int* conn = open_conn(handle);
auto delete_binded = std::bind(inter::delete_conn, std::placeholders::_1, handle);
return std::unique_ptr<int, decltype(delete_binded)>(conn, delete_binded);
}