当unique_ptr被销毁时,如何检索pclose的返回值?

Joh*_*ohn 1 c++ lambda smart-pointers unique-ptr c++11

正如 @user17732522 指出的那样, 的删除器std::unique_ptr应该可以用一个指针作为参数来调用。

如何检索pcloseunique_ptr 被销毁时的返回值?

代码片段无法编译,

#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()
{

}
Run Code Online (Sandbox Code Playgroud)

而下面的代码片段可以编译。

#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()
{

}
Run Code Online (Sandbox Code Playgroud)

以下是编译器对前一个代码片段的抱怨:

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));
      |           ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

我尝试使用此代码片段来获取返回值,但它无法编译:

#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()
{

}
Run Code Online (Sandbox Code Playgroud)

有人能解释一下这个问题吗?

JeJ*_*eJo 7

由于您只能提供一个自定义删除器,该删除器可以使用一个指针作为参数进行调用,因此您不能将带有两个参数的 lambda 作为删除器。

带捕获的 lambda 也不起作用,因为它无法转换为函数指针(即只有无状态 lambda 可以转换为自由函数指针类型)


当 pclose 被销毁时,如何检索 pclose 的返回值std::unique_ptr

使用 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;
}
Run Code Online (Sandbox Code Playgroud)

查看演示

  • @John 只需初始化 `ret = -1` 即可。如果`FILE*`是`nullptr`,它不会被覆盖。 (2认同)