Hello all, I'm in a process of writing a small Linux C++ program for discovering repeaded files over a filesystem. One part of this task is traversing a directory structure. This is done by the following recursive function. Since I'd like it to be general enough to handle function pointers and function objects I've made it a template.
template <typename CallBack> void Traverse(const std::string& path, CallBack& callback) throw (PosixError); This brings an interesting problem: if I make second parameter is const (and I'd like it to be that way) then: 1) G++ 3.3.6 refuses to compile the program error: no matching function for call to `Traverse(char*&, void (&)(const std::string&))' 2) G++ 4.1.1 compiles the program but the callback is never executed (i.e. no output) if the callback is function. Works fine if given a function objects. Is it some kind of compliler issue or maybe a C++ mistake in my code? TIA, Kyku Update: prefixing Traverse argument with & solves the problem in both g++3 and 4. But then I always thought Function name on its own is equivalent to its adress. Here's the working part of the program: #include <string> #include <cstddef> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <errno.h> class PosixError : public std::exception { public: PosixError() : _M_code(errno), _M_rep(strerror(_M_code)) {} PosixError(int code) : _M_code(code), _M_rep(strerror(_M_code)) {} int Code() const { return _M_code; } const char* what() const throw() { return _M_rep.c_str(); } ~PosixError() throw() {} private: int _M_code; std::string _M_rep; }; class DirEntry { public: const std::string& Name() { return _M_name; } operator bool () const { return !_M_name.empty(); } private: DirEntry(struct dirent* dent) : _M_name(dent ? dent->d_name : "") {} std::string _M_name; friend class DirWalker; }; class DirWalker { public: DirWalker(const std::string& dirname) throw (PosixError) { _M_dir = 0; Open(dirname); } ~DirWalker() { if (_M_dir != 0) closedir(_M_dir); } operator bool () const { return _M_dir != 0; } void Open(const std::string& dirname) throw (PosixError) { Close(); _M_dir = opendir(dirname.c_str()); if (_M_dir == 0) throw PosixError(); } void Close() { if (_M_dir != 0) { closedir(_M_dir); _M_dir = 0; } } DirEntry Read() throw(PosixError) { const char* name; struct dirent* dent; do { errno = 0; dent = readdir(_M_dir); if (errno != 0) throw PosixError(); name = dent->d_name; } while (dent != 0 && name[0] == '.' && (name[1] == '\0' || name[1] == '.' && name[2] == '\0')); return DirEntry(dent); } private: DIR* _M_dir; }; template <typename CallBack> void Traverse(const std::string& path, CallBack& callback) throw (PosixError) { DirWalker dw(path); while (DirEntry de = dw.Read()) { try { struct stat buf; std::string fullpath = path + '/' + de.Name(); if (stat(fullpath.c_str(), &buf) < 0) throw PosixError(); callback(fullpath); if (S_ISDIR(buf.st_mode)) Traverse(fullpath, callback); } catch (PosixError& pe) { if (pe.Code() == EACCES) continue; throw; } } } #include <iostream> void PrintString(const std::string& name) { std::cout << name << std::endl; } int main(int argc, char *argv[]) { for (int i = 1; i < argc; ++i) Traverse(argv[i], PrintString); } _______________________________________________ help-gplusplus mailing list help-gplusplus@gnu.org http://lists.gnu.org/mailman/listinfo/help-gplusplus