当 unique_ptr 被销毁时,如何检索 pclose 的 return 值?
How can I retrieve the return value of pclose when the unique_ptr is destroyed?
正如@user17732522 指出的那样,std::unique_ptr
的删除器应该可以用 恰好一个指针 作为参数来调用。
当 unique_ptr 被销毁时,如何取回 pclose
的 return 值?
这个code snippet不编译,
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*, int*)> pipe(popen(cmd.c_str(), "r"), [](FILE* file, int* ret_ptr){
if(NULL==file)
{
*ret_ptr = -1;
}
else
{
*ret_ptr = pclose(file);
}
});
}
return ret;
}
int main()
{
}
而下面的 code snippet 编译。
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*)> pipe(popen(cmd.c_str(), "r"), [](FILE* file){
if(NULL==file)
{
}
else
{
pclose(file);
}
});
}
return ret;
}
int main()
{
}
这是编译器对前一个代码片段的抱怨:
In file included from /opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/memory:76,
from <source>:1:
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = _IO_FILE; _Dp = void (*)(_IO_FILE*, int*)]':
<source>:20:27: required from here
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:357:63: error: static assertion failed: unique_ptr's deleter must be invocable with a pointer
357 | static_assert(__is_invocable<deleter_type&, pointer>::value,
| ^~~~~
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:357:63: note: 'std::integral_constant<bool, false>::value' evaluates to false
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:361:24: error: too few arguments to function
361 | get_deleter()(std::move(__ptr));
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
我试过这个 code snippet 来获取 return 值,但它没有编译:
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*)> pipe(popen(cmd.c_str(), "r"), [&ret](FILE* file){
if(NULL==file)
{
ret = -1;
}
else
{
ret = pclose(file);
}
});
}
return ret;
}
int main()
{
}
有人能解释一下这件事吗?
因为您只能提供一个 custom deleter which can be callable with exactly one pointer 作为参数,所以您不能将带有两个参数的 lambda 作为删除器。
你的带捕获的 lambda 也将不起作用,因为 (即只有无状态的 lambda 可以转换为自由函数指针类型)
How can I retrieve the return value of pclose when the std::unique_ptr
is destroyed?
使用 lambda
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
const auto deleter = [&ret](FILE* file) { ret = file ? pclose(file) : 0; };
{
std::unique_ptr<FILE, decltype(deleter)> pipe(popen(cmd.c_str(), "r"), deleter);
}
return ret;
}
感谢@Jelo,@Some 程序员,@user17732522。
对于这篇 post 的读者来说,this code snippet 也很有效。
#include<memory>
#include<iostream>
#include<string>
#include<stdio.h>
#include<functional>
using std::placeholders::_1;
void ClosePipe(FILE* file, int& ret)
{
ret = pclose(file);
return;
}
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = -1;
auto delete_binded = std::bind(ClosePipe, _1, std::ref(ret));
{
std::unique_ptr<FILE, decltype(delete_binded) > pipe{popen(cmd.c_str(), "r"), delete_binded};
}
return ret;
}
int main()
{
}
由于您不使用 output
,可以将其删除。您需要通过引用传递 ret
到删除器,以便它可以被结果修改。三元运算符可以帮助减少 if
块,因为如果 fp
是空指针,则计算结果为 false
。你可以用decltype
获取deleter
的类型,这样它就可以很容易地传递给std::unique_ptr
的模板。
int execCmd(const std::string& cmd) {
int ret{};
auto deleter = [&ret](FILE* fp) { ret = fp ? pclose(fp) : 0; };
{
std::unique_ptr<FILE, decltype(deleter)> pipe{popen(cmd.c_str(), "r"),
deleter};
}
return ret;
}
正如@user17732522 指出的那样,std::unique_ptr
的删除器应该可以用 恰好一个指针 作为参数来调用。
当 unique_ptr 被销毁时,如何取回 pclose
的 return 值?
这个code snippet不编译,
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*, int*)> pipe(popen(cmd.c_str(), "r"), [](FILE* file, int* ret_ptr){
if(NULL==file)
{
*ret_ptr = -1;
}
else
{
*ret_ptr = pclose(file);
}
});
}
return ret;
}
int main()
{
}
而下面的 code snippet 编译。
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*)> pipe(popen(cmd.c_str(), "r"), [](FILE* file){
if(NULL==file)
{
}
else
{
pclose(file);
}
});
}
return ret;
}
int main()
{
}
这是编译器对前一个代码片段的抱怨:
In file included from /opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/memory:76,
from <source>:1:
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = _IO_FILE; _Dp = void (*)(_IO_FILE*, int*)]':
<source>:20:27: required from here
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:357:63: error: static assertion failed: unique_ptr's deleter must be invocable with a pointer
357 | static_assert(__is_invocable<deleter_type&, pointer>::value,
| ^~~~~
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:357:63: note: 'std::integral_constant<bool, false>::value' evaluates to false
/opt/compiler-explorer/gcc-11.3.0/include/c++/11.3.0/bits/unique_ptr.h:361:24: error: too few arguments to function
361 | get_deleter()(std::move(__ptr));
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
我试过这个 code snippet 来获取 return 值,但它没有编译:
#include<memory>
#include<iostream>
#include<string>
#include<cstdio>
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
{
std::unique_ptr<FILE, void(*)(FILE*)> pipe(popen(cmd.c_str(), "r"), [&ret](FILE* file){
if(NULL==file)
{
ret = -1;
}
else
{
ret = pclose(file);
}
});
}
return ret;
}
int main()
{
}
有人能解释一下这件事吗?
因为您只能提供一个 custom deleter which can be callable with exactly one pointer 作为参数,所以您不能将带有两个参数的 lambda 作为删除器。
你的带捕获的 lambda 也将不起作用,因为
How can I retrieve the return value of pclose when the
std::unique_ptr
is destroyed?
使用 lambda
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = 0;
const auto deleter = [&ret](FILE* file) { ret = file ? pclose(file) : 0; };
{
std::unique_ptr<FILE, decltype(deleter)> pipe(popen(cmd.c_str(), "r"), deleter);
}
return ret;
}
感谢@Jelo,@Some 程序员,@user17732522。
对于这篇 post 的读者来说,this code snippet 也很有效。
#include<memory>
#include<iostream>
#include<string>
#include<stdio.h>
#include<functional>
using std::placeholders::_1;
void ClosePipe(FILE* file, int& ret)
{
ret = pclose(file);
return;
}
int ExecCmd(const std::string& cmd, std::string& output)
{
int ret = -1;
auto delete_binded = std::bind(ClosePipe, _1, std::ref(ret));
{
std::unique_ptr<FILE, decltype(delete_binded) > pipe{popen(cmd.c_str(), "r"), delete_binded};
}
return ret;
}
int main()
{
}
由于您不使用 output
,可以将其删除。您需要通过引用传递 ret
到删除器,以便它可以被结果修改。三元运算符可以帮助减少 if
块,因为如果 fp
是空指针,则计算结果为 false
。你可以用decltype
获取deleter
的类型,这样它就可以很容易地传递给std::unique_ptr
的模板。
int execCmd(const std::string& cmd) {
int ret{};
auto deleter = [&ret](FILE* fp) { ret = fp ? pclose(fp) : 0; };
{
std::unique_ptr<FILE, decltype(deleter)> pipe{popen(cmd.c_str(), "r"),
deleter};
}
return ret;
}