Help us understand the problem. What is going on with this article?

fstreamのファイルディスクリプタを取得する

パイプとかファイルディスクリプタとか、そーゆー低レイヤーのはなし
boost::processの子プロセスの入力を閉じる https://qiita.com/cielavenir/items/9219162170cf2dd8b144
サブプロセス処理をパイプを使わずに行う https://qiita.com/cielavenir/items/0e69848b705fafec86e1
fstreamのファイルディスクリプタを取得する
ムーブコンストラクタしかないクラスのprotectedメンバを呼び出す
https://qiita.com/cielavenir/items/fe892c564e6b12983776
  • _M_file.fd()を呼び出せば達成できますが、このメンバはprotectedです。
  • 以下の手順により達成可能です。
    1. basic_filebufを継承したクラス(basic_filebufFd)を宣言します。
    2. basic_filebufFdを、元のbasic_filebuf(rdbuf)の右辺値参照により実体化(rdbufFd)します。
    3. rdbufFd上で必要な処理を行います。
    4. rdbufに、rdbufFdをbasic_filebufにキャストしたものをムーブします。
  • 結果として、ムーブコンストラクタしかないクラスのprotectedメンバを呼び出すサンプルにもなってしまっています--;;;

※libstdc++であれば、g++/clang++ともに意図した動作をします。

いやーもう https://github.com/gcc-mirror/gcc/commit/a0bda314a53cb42fbbc2012c0241409b3e8be5d3 に感謝やなorz


#include <fstream>
#include <stdio.h>

template<typename _CharT>
class basic_filebufFd : public std::basic_filebuf<_CharT>
{
public:
    basic_filebufFd(std::basic_filebuf<_CharT>&& other):std::basic_filebuf<_CharT>(std::move(other)){
    }
    int fd()
    {
        return this->_M_file.fd();
    }
};
int _GetFstreamFd(std::ios &f){
    if(std::fstream* fin = dynamic_cast<std::fstream*>(&f)){
        if(!fin->is_open()){
            return -1;
        }
        std::basic_filebuf<std::fstream::char_type> &rdbuf = *fin->rdbuf();
        basic_filebufFd<std::fstream::char_type> rdbufFd(std::move(rdbuf));
        int fd = rdbufFd.fd();
        rdbuf = std::move( *(typeof(rdbuf)*)&rdbufFd );
        return fd;
    }
    if(std::ifstream* fin = dynamic_cast<std::ifstream*>(&f)){
        if(!fin->is_open()){
            return -1;
        }
        std::basic_filebuf<std::ifstream::char_type> &rdbuf = *fin->rdbuf();
        basic_filebufFd<std::ifstream::char_type> rdbufFd(std::move(rdbuf));
        int fd = rdbufFd.fd();
        rdbuf = std::move( *(typeof(rdbuf)*)&rdbufFd );
        return fd;
    }
    if(std::ofstream* fin = dynamic_cast<std::ofstream*>(&f)){
        if(!fin->is_open()){
            return -1;
        }
        std::basic_filebuf<std::ofstream::char_type> &rdbuf = *fin->rdbuf();
        basic_filebufFd<std::ofstream::char_type> rdbufFd(std::move(rdbuf));
        int fd = rdbufFd.fd();
        rdbuf = std::move( *(typeof(rdbuf)*)&rdbufFd );
        return fd;
    }
    return -1;
}

int main(){
    std::fstream f("hello.txt",std::ios::in | std::ios::out | std::ios::trunc);
    f.write("hello\n",6);
    f.seekp(0,std::ios::beg);
    f.flush();
    std::istream &in = f;
    if(1){
        int fd=_GetFstreamFd(f);
        if(fd<0){
            puts("failed to get fd");
            return 1;
        }
        std::string fname = std::string("/dev/fd/")+std::to_string(fd);
        puts("fd read");
        system(std::string("cat "+fname).c_str());
    }
    puts("rdbuf read");
    std::string line;
    std::getline(f,line);
    puts(line.c_str());
}
  • これはまじな話なんですが、boost::processもcielavenir/mini7zも導入が却下されたため、放心状態が続いていますorz まだ審議中だけど、俺的には(boost::processやcielavenir/mini7zを使った版と比べて)こっちのほうがよほどクソコードなんですよね…
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした