我可以在C ++中将ftw函数用于类方法吗?

时间:2018-11-23 11:06:04

标签: c++ linux

我想使用ftw-function递归遍历文件系统结构。另外,该方法应在类内部使用。同样,nftw()调用的入口函数属于同一类。之所以如此,是因为入口函数应该根据找到的文件来更改某些类成员。

实施这种方法时,出现错误(见下文)。这是语法问题,还是无法将指向方法的指针转发到nftw()?如果不可能,您是否知道其他方法可以在Linux下重新遍历文件系统结构?

class model
{
  public:
    boost::unordered_map<std::string, int> map;

    int configure(const char *name)
    {
        // ...
        ftw("DTModels/", this->ftw_entry, 15);
        // ...

        return = 0;
    }


  private:

    int ftw_entry(const char *filepath, const struct stat *info, const int typeflag)
    {
        // Here I want to change the member 'map'
        std::string filepath_s = filepath;
        std::cout << "FTW_Entry: " << filepath_s << std::endl;
    }
};


ERROR:
a pointer to a bound function may only be used to call the function
      ftw("DTModels/", this->ftw_entry, 15);

1 个答案:

答案 0 :(得分:0)

我已经很多年没有使用过ftw了,既然您要求使用其他方法,请看看std::filesystem(C ++ 17)。许多C ++ 17之前的安装都可以通过boostexperimental使用它。如果您使用的是C ++ 17之前的实现方式,那么您需要从下面删除一些stat行才能使其正常工作。

#include <iostream>

//#define I_HAVE_BOOST

#if __cplusplus >= 201703L
  #include <filesystem>
  namespace fs = std::filesystem;
#elif I_HAVE_BOOST
  #include <boost/filesystem.hpp>
  namespace fs = boost::filesystem;
#else
  #include <experimental/filesystem>
  namespace fs = std::experimental::filesystem;
#endif

auto& out = std::cout;

void show_dent(const fs::directory_entry& dent) {
    static size_t indent=0;
    std::string ind(indent, ' ');

    fs::file_status lstat = dent.symlink_status();

    if( fs::is_symlink(lstat) ) {
        fs::path pp = fs::read_symlink(dent);
        out << ind << dent << " -> " << pp << "\n";
        ++indent;
        show_dent(fs::directory_entry(pp));
        --indent;
    } else {
        if(fs::is_directory(dent)) {
            fs::directory_iterator dit_end;

            std::cout << "Directory " << dent << " includes the following files:\n";
            ++indent;
            for(auto dit = fs::directory_iterator(dent); dit != dit_end; ++dit) {
                show_dent(*dit);
            }
            --indent;
        } else {
            fs::file_status stat = dent.status();

            out << ind << dent << "\n"
                << ind << " stat\n"
                << ind << "  is_regular_file  : " << fs::is_regular_file(stat) << "\n"
                << ind << "  is_directory     : " << fs::is_directory(stat) << "\n"
                << ind << "  is_block_file    : " << fs::is_block_file(stat) << "\n"
                << ind << "  is_character_file: " << fs::is_character_file(stat) << "\n"
                << ind << "  is_fifo          : " << fs::is_fifo(stat) << "\n"
                << ind << "  is_socket        : " << fs::is_socket(stat) << "\n"
                << ind << "  is_symlink       : " << fs::is_symlink(stat) << "\n"
                << ind << "  exists           : " << fs::exists(stat) << "\n";
            if( fs::is_regular_file(stat) ) {
                out
                << ind << "  file_size        : " << fs::file_size(dent) << "\n";
            }
        }
    }
}

int main(int argc, char* argv[]) {
    std::vector<std::string> args(argv+1, argv+argc);

    out << std::boolalpha;

    for(const auto& file_or_dir : args) {
        show_dent(fs::directory_entry(file_or_dir));
    }

    return 0;
}