Issue
As @user17732522 pointed out that the deleter of std::unique_ptr
is supposed to be callable with exactly one pointer as argument.
How can I retrieve the return value of pclose
when the unique_ptr is destroyed?
This code snippet does not compile,
#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()
{
}
Whereas this code snippet below compiles.
#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()
{
}
Here is what the compiler complains about the former code snippet:
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));
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
I tried this code snippet to acquire the return value, but it does not compile:
#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()
{
}
Could anybody shed some light on this matter?
Solution
Since you can only provide a custom deleter which can be callable with exactly one pointer as argument, you can not have the lambda with two arguments in it as deleter.
Your lambda with capture will also not work, as it can not be converted to a pointer to a function (i.e. only stateless lambdas can be converted to free function pointers type)
How can I retrieve the return value of pclose when the
std::unique_ptr
is destroyed?
Using 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;
}
Answered By - JeJo Answer Checked By - Robin (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.