C++ 对于仅标头的库来说,这是否太多代码?

C++ 对于仅标头的库来说,这是否太多代码?,c++,header-files,header-only,C++,Header Files,Header Only,似乎我必须在这里内联相当多的代码。我想知道,将其完全保留在这样的头文件中是否是一种糟糕的设计实践: #include <list> #include <string> #include <boost/noncopyable.hpp> #include <boost/make_shared.hpp> #include <boost/iterator/iterator_facade.hpp> #include <Windows.h&g

似乎我必须在这里内联相当多的代码。我想知道,将其完全保留在这样的头文件中是否是一种糟糕的设计实践:

#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)

}}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“./Exception.hpp”
命名空间WindowsAPI{命名空间文件系统{
类非递归枚举;
类递归枚举;
结构所有结果;
结构文件;
模板
类目录迭代器;
模板
结构文件数据;
类非递归枚举:public boost::noncopyable
{
WIN32_FIND_DATAW currentData;
处理高频风;
std::wstring根;
公众:
非递归枚举():hFind(无效的句柄值){
};
非递归枚举(常量std::wstring和pathSpec){
std::wstring::const_迭代器lastSlash=
std::find(pathSpec.rbegin(),pathSpec.rend(),L'\\').base();
if(lastSlash!=pathSpec.end())
分配(pathSpec.begin(),lastSlash);
hFind=FindFirstFileW(pathSpec.c_str(),¤tData);
if(hFind==无效的句柄值)
WindowsApiException::ThrowFromLastError();
而(!wcscmp(currentData.cFileName,L.“)| |!wcscmp(currentData.cFileName,L.“.”){
增量();
}
};
无效增量(){
布尔成功=
FindNextFile(hFind和currentData);
如果(成功)
返回;
DWORD error=GetLastError();
如果(错误==错误\u没有\u更多\u文件){
FindClose(hFind);
hFind=无效的句柄值;
}否则{
WindowsApiException::抛出(错误);
}
};
~nonrecreasiveenumeration(){
if(hFind!=无效的句柄值)
FindClose(hFind);
};
布尔相等(常数非递归枚举和其他)常数{
如果(此==&其他)
返回true;
返回hFind==other.hFind;
};
常量std::wstring&GetPathRoot()常量{
返回根;
};
常量WIN32\u FIND\u DATAW&GetCurrentFindData()常量{
返回当前数据;
};
};
//尚未实施
类递归枚举:public boost::noncopyable
{
};
模板
struct FileData//充当迭代器中WIN32_FIND_数据结构的代理。
{
const Recurse_T*impl;
模板
FileData(const DirectoryIterator*parent):impl(parent->impl.get()){};
DWORD GetAttributes()常量{
返回impl->GetCurrentFindData().dwFileAttributes;
};
bool IsDirectory()常量{
返回(GetAttributes()&文件属性目录)!=0;
};
bool IsFile()常量{
return!IsDirectory();
};
bool IsArchive()常量{
返回(GetAttributes()&文件属性存档)!=0;
};
bool IsReadOnly()常量{
返回(GetAttributes()&文件属性只读)!=0;
};
未签名的\uuu int64 GetSize()常量{
ULARGE_整数值;
intValue.LowPart=impl.GetCurrentFindData().nFileSizeLow;
intValue.HighPart=impl.GetCurrentFindData().nFileSizeHigh;
返回intValue.QuadPart;
};
std::wstring GetFolderPath()常量{
返回impl->GetPathRoot();
};
std::wstring GetFileName()常量{
返回impl->GetCurrentFindData().cFileName;
};
std::wstring GetFullFileName()常量{
返回GetFolderPath()+GetFileName();
};
std::wstring GetShortFileName()常量{
返回impl->GetCurrentFindData().cAlternateFileName;
};
FILETIME GetCreationTime()常量{
返回impl->GetCurrentFindData().ftCreationTime;
};
FILETIME GetLastAccessTime()常量{
返回impl->GetCurrentFindData().ftLastAccessTime;
};
FILETIME GetLastWriteTime()常量{
返回impl->GetCurrentFindData().ftLastWriteTime;
};
};
结构所有结果
{
模板
bool运算符()(const FileData&){
返回true;
};
}; 
仅结构文件
{
模板
布尔运算符()(常量文件数据和参数){
返回arg.IsFile();
};
};
#pragma警告(推送)
#杂注警告(禁用:4355)
模板
类DirectoryIterator:public boost::iterator\u facade
{
朋友类boost::迭代器\u核心\u访问;
boost::共享\u ptr impl;
文件数据删除数据;
过滤器(T过滤器),;
无效增量(){
做{
impl->increment();
}而(!filter(derefData));
};
布尔相等(常量目录迭代器和其他)常量{
返回impl->equal(*other.impl);
};
常量FileData&dereference()常量{
返回数据;
};
公众:
typedef FileData数据类型;
友元结构数据类型;
DirectoryIterator(Filter\u T functor=Filter\u T()):
impl(boost::make_shared()),
derefData(本文件),
过滤器(函子){
};
显式目录迭代器(const std::wstring&pathSpec,Filter\u T functor=Filter\u T()):
impl(boost::make_shared(pathSpec)),
derefData(本文件),
过滤器(函子){
};
};
#布拉格警告(pop)
}}

如果有什么安慰的话,我的一些作品中有更多的代码。而且所有C++标准库实现,Boost和微软(例如,ATL)。

< P>只要页眉的长度在你的头文件中,你可以拥有你想要的代码。取舍是每次构建程序时必须重新编译的代码量;放置在CPP文件中的代码可以编译成对象文件,并在每个后续生成中链接

我建议将
directoryinteratorimpl
的每个方法定义都移动到
.cpp
文件中。如果您没有在类定义中定义内联方法,则没有理由将其包含在头文件中

一个不相关的旁白:避免编写
inline directoryinteratorimpl()-实际将内联函数内联编写,或者不将其标记为内联。从:

函数的