PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, November 5, 2022

[FIXED] How can I retrieve the return value of pclose when the unique_ptr is destroyed?

 November 05, 2022     c++, c++11, lambda, smart-pointers, unique-ptr     No comments   

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;
}

See a demo



Answered By - JeJo
Answer Checked By - Robin (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing