Vra

Dit lyk asof ek moes nogal 'n bietjie van die kode hier inline. Ek wonder of dit se slegte ontwerp praktyk om hierdie laat heeltemal in 'n kop-lêer soos hierdie:

#include <list>
#include <string>
#include <boost/noncopyable.hpp>
#include <boost/make_shared.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <Windows.h>
#include "../Exception.hpp"

namespace WindowsAPI { namespace FileSystem {

class NonRecursiveEnumeration;
class RecursiveEnumeration;
struct AllResults;
struct FilesOnly;

template <typename Filter_T = AllResults, typename Recurse_T = NonRecursiveEnumeration>
class DirectoryIterator;

template <typename Recurse_T>
struct FileData;

class NonRecursiveEnumeration : public boost::noncopyable
{
    WIN32_FIND_DATAW currentData;
    HANDLE hFind;
    std::wstring root;
public:
    NonRecursiveEnumeration() : hFind(INVALID_HANDLE_VALUE) {
    };
    NonRecursiveEnumeration(const std::wstring& pathSpec) {
        std::wstring::const_iterator lastSlash =
            std::find(pathSpec.rbegin(), pathSpec.rend(), L'\\').base();
        if (lastSlash != pathSpec.end())
            root.assign(pathSpec.begin(), lastSlash);
        hFind = FindFirstFileW(pathSpec.c_str(), &currentData);
        if (hFind == INVALID_HANDLE_VALUE)
            WindowsApiException::ThrowFromLastError();
        while (!wcscmp(currentData.cFileName, L".") || !wcscmp(currentData.cFileName, L"..")) {
            increment();
        }
    };
    void increment() {
        BOOL success =
            FindNextFile(hFind, &currentData);
        if (success)
            return;
        DWORD error = GetLastError();
        if (error == ERROR_NO_MORE_FILES) {
            FindClose(hFind);
            hFind = INVALID_HANDLE_VALUE;
        } else {
            WindowsApiException::Throw(error);
        }
    };
    ~NonRecursiveEnumeration() {
        if (hFind != INVALID_HANDLE_VALUE)
            FindClose(hFind);
    };
    bool equal(const NonRecursiveEnumeration& other) const {
        if (this == &other)
            return true;
        return hFind == other.hFind;
    };
    const std::wstring& GetPathRoot() const {
        return root;
    };
    const WIN32_FIND_DATAW& GetCurrentFindData() const {
        return currentData;
    };
};

//Not implemented yet
class RecursiveEnumeration : public boost::noncopyable
{
};

template <typename Recurse_T>
struct FileData //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator.
{
    const Recurse_T* impl;
    template <typename Filter_T, typename Recurse_T>
    FileData(const DirectoryIterator<Filter_T, Recurse_T>* parent) : impl(parent->impl.get()) {};
    DWORD GetAttributes() const {
        return impl->GetCurrentFindData().dwFileAttributes;
    };
    bool IsDirectory() const {
        return (GetAttributes() & FILE_ATTRIBUTE_DIRECTORY) != 0;
    };
    bool IsFile() const {
        return !IsDirectory();
    };
    bool IsArchive() const {
        return (GetAttributes() & FILE_ATTRIBUTE_ARCHIVE) != 0;
    };
    bool IsReadOnly() const {
        return (GetAttributes() & FILE_ATTRIBUTE_READONLY) != 0;
    };
    unsigned __int64 GetSize() const {
        ULARGE_INTEGER intValue;
        intValue.LowPart = impl.GetCurrentFindData().nFileSizeLow;
        intValue.HighPart = impl.GetCurrentFindData().nFileSizeHigh;
        return intValue.QuadPart;
    };
    std::wstring GetFolderPath() const {
        return impl->GetPathRoot();
    };
    std::wstring GetFileName() const {
        return impl->GetCurrentFindData().cFileName;
    };
    std::wstring GetFullFileName() const {
        return GetFolderPath() + GetFileName();
    };
    std::wstring GetShortFileName() const {
        return impl->GetCurrentFindData().cAlternateFileName;
    };
    FILETIME GetCreationTime() const {
        return impl->GetCurrentFindData().ftCreationTime;
    };
    FILETIME GetLastAccessTime() const {
        return impl->GetCurrentFindData().ftLastAccessTime;
    };
    FILETIME GetLastWriteTime() const {
        return impl->GetCurrentFindData().ftLastWriteTime;
    };
};

struct AllResults
{
    template <typename Recurse_T>
    bool operator()(const FileData<Recurse_T>&) {
        return true;
    };
}; 

struct FilesOnly
{
    template <typename Recurse_T>
    bool operator()(const FileData<Recurse_T>& arg) {
        return arg.IsFile();
    };
};

#pragma warning(push)
#pragma warning(disable: 4355)
template <typename Filter_T, typename Recurse_T>
class DirectoryIterator : public boost::iterator_facade<DirectoryIterator<Filter_T>, const FileData<Recurse_T>, std::input_iterator_tag>
{
    friend class boost::iterator_core_access;
    boost::shared_ptr<Recurse_T> impl;
    FileData<Recurse_T> derefData;
    Filter_T filter;
    void increment() {
        do {
            impl->increment();
        } while (! filter(derefData));
    };
    bool equal(const DirectoryIterator& other) const {
        return impl->equal(*other.impl);
    };
    const FileData<Recurse_T>& dereference() const {
        return derefData;
    };
public:
    typedef FileData<Recurse_T> DataType;
    friend struct DataType;
    DirectoryIterator(Filter_T functor = Filter_T()) :
        impl(boost::make_shared<Recurse_T>()),
        derefData(this),
        filter(functor) {
    };
    explicit DirectoryIterator(const std::wstring& pathSpec, Filter_T functor = Filter_T()) :
        impl(boost::make_shared<Recurse_T>(pathSpec)),
        derefData(this),
        filter(functor) {
    };
};
#pragma warning(pop)

}}
Was dit nuttig?

Oplossing

Ek het baie meer kode in 'n paar van my, as dit is van enige troos. en so doen al C ++ Standard Biblioteek implementering, Boost en Microsoft (byvoorbeeld, ATL).

Ander wenke

Die enigste deel wat lyk my as oop vir veel vraag sou die implementering van die funksies in DirectoryIteratorImpl wees. Dit is nie 'n sjabloon sodat dit nie regtig hoef te wees in 'n kop, en dit het 'n paar ietwat langer roetines (die "regte" constructor en die verhoging).

Die res is óf templates of anders saamgestel uit so 'n triviale funksies wat jy hulle wil hê inline in elk geval (bv die lede van FileData). Diegene sal eindig in 'n kop-in elk geval.

Wat die lengte van die kop gaan, jy kan soveel kode as jy wil in jou kop lêers. Die handel af is die bedrag van kode wat elke keer as jou program is gebou moet word hersaamgestel; kode geplaas in jou CPP-lêers kan word saamgestel in voorwerp lêers en gekoppel in op elke daaropvolgende opbou.

Ek stel voor dat elk van die metode definisies vir DirectoryIteratorImpl moet geskuif word na 'n .cpp lêer. As jy nie die definisie van 'n metode inline binne 'n klas definisie, daar is geen rede vir dit wat ingesluit moet word in die kop lêer.

'n onverwante eenkant: Vermy skryf inline DirectoryIteratorImpl(); - eintlik skryf jou inline funksies inline, of hulle nie 'inline merk. Van die C ++ Vrae Lite :

  

Dit is gewoonlik noodsaaklik dat definisie van die funksie se (die deel tussen die {...})   in 'n kop-lêer geplaas word. As jy sit definisie die inline funksie se toetrede tot 'n Cpp   lêer, en as dit vandag genoem word uit 'n ander Cpp lêer, sal jy 'n "onopgeloste eksterne" kry   fout van die linkerkant.

As u funksies is "te groot" te skryf in die kop lêer, hulle is te groot om 'inline en die samesteller sal waarskynlik anyways ignoreer jou inline voorstel.

Dit blyk dat u programmering vir Windows hier, sal ons aanneem dat jy met behulp van Visual Studio?

In elk geval, ek dink nie daar is iets soos te veel kode in kop.

Dit is 'n kwessie van handel offs meestal:

  • stadiger samestelling (maar ons het multicores en compileerde headers)
  • meer gereelde hersamestelling (weer, multicores)
  • miskien kode opblaas ...

Die enigste punt wat irriterende (in my opinie) is die jongste ... en ek sal help hier nodig: ons seker die funksies gaan word inlined, is dit nie moontlik dat die samesteller en linker besluit nie om hulle inline en omskep dit in 'n gereelde oproep?

Om eerlik te wees, ek sou nie te veel oor wat bekommer. 'N Aantal Boost biblioteke is kop-net nog vir hulle nie-sjabloon dele bloot omdat dit integrasie maak makliker (geen Ontkoppeling vereis).

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top