diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2019-08-11 17:57:34 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2019-08-11 17:57:34 (GMT) |
commit | 3e8fe63473b047bf3d48c734750334244e9981a8 (patch) | |
tree | 3d2f224b78898feb3c4b88cc5e904f5da4284f06 | |
parent | 09c263e70a2ac9afbe8f7cc7a0a07c5ab069645a (diff) | |
download | Doxygen-3e8fe63473b047bf3d48c734750334244e9981a8.zip Doxygen-3e8fe63473b047bf3d48c734750334244e9981a8.tar.gz Doxygen-3e8fe63473b047bf3d48c734750334244e9981a8.tar.bz2 |
Reduce boilerplate code by using C++11 variadic templates and perfect forwarding
-rw-r--r-- | src/index.h | 75 | ||||
-rw-r--r-- | src/outputlist.cpp | 159 | ||||
-rw-r--r-- | src/outputlist.h | 79 |
3 files changed, 32 insertions, 281 deletions
diff --git a/src/index.h b/src/index.h index c6baba5..f571375 100644 --- a/src/index.h +++ b/src/index.h @@ -18,6 +18,7 @@ #ifndef INDEX_H #define INDEX_H +#include <utility> #include <qlist.h> #include <qcstring.h> @@ -55,61 +56,17 @@ class IndexList : public IndexIntf private: QList<IndexIntf> m_intfs; - // --- foreach implementations for various number of arguments - - void foreach(void (IndexIntf::*methodPtr)()) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(); - } - - template<typename A1> - void foreach(void (IndexIntf::*methodPtr)(A1),A1 a1) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1); - } - - template<typename A1,typename A2,typename A3> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3),A1 a1,A2 a2,A3 a3) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3); - } - - template<typename A1,typename A2,typename A3,typename A4> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3,A4),A1 a1,A2 a2,A3 a3,A4 a4) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3,a4); - } - - template<typename A1,typename A2,typename A3,typename A4,typename A5> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3,A4,A5),A1 a1,A2 a2,A3 a3,A4 a4,A5 a5) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3,a4,a5); - } - - template<typename A1,typename A2,typename A3,typename A4,typename A5,typename A6> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3,A4,A5,A6),A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3,a4,a5,a6); - } - - template<typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3,A4,A5,A6,A7,A8),A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8) - { - QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3,a4,a5,a6,a7,a8); - } - - template<typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9> - void foreach(void (IndexIntf::*methodPtr)(A1,A2,A3,A4,A5,A6,A7,A8,A9),A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9) + // For each index format we forward the method call. + // We use C++11 variadic templates and perfect forwarding to implement foreach() generically, + // and split the types of the methods from the arguments passed to allow implicit conversions. + template<class... Ts,class... As> + void foreach(void (IndexIntf::*methodPtr)(Ts...),As&&... args) { QListIterator<IndexIntf> li(m_intfs); - for (li.toFirst();li.current();++li) (li.current()->*methodPtr)(a1,a2,a3,a4,a5,a6,a7,a8,a9); + for (li.toFirst();li.current();++li) + { + (li.current()->*methodPtr)(std::forward<As>(args)...); + } } public: @@ -137,17 +94,15 @@ class IndexList : public IndexIntf void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor,bool separateIndex=FALSE,bool addToNavIndex=FALSE, const Definition *def=0) - { if (m_enabled) foreach<bool,const char *,const char *,const char *,const char*,bool,bool,const Definition *> - (&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); } + { if (m_enabled) foreach(&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); } void addIndexItem(const Definition *context,const MemberDef *md,const char *sectionAnchor=0,const char *title=0) - { if (m_enabled) foreach<const Definition *,const MemberDef *,const char *,const char *> - (&IndexIntf::addIndexItem,context,md,sectionAnchor,title); } + { if (m_enabled) foreach(&IndexIntf::addIndexItem,context,md,sectionAnchor,title); } void addIndexFile(const char *name) - { if (m_enabled) foreach<const char *>(&IndexIntf::addIndexFile,name); } + { if (m_enabled) foreach(&IndexIntf::addIndexFile,name); } void addImageFile(const char *name) - { if (m_enabled) foreach<const char *>(&IndexIntf::addImageFile,name); } + { if (m_enabled) foreach(&IndexIntf::addImageFile,name); } void addStyleSheetFile(const char *name) - { if (m_enabled) foreach<const char *>(&IndexIntf::addStyleSheetFile,name); } + { if (m_enabled) foreach(&IndexIntf::addStyleSheetFile,name); } private: bool m_enabled; diff --git a/src/outputlist.cpp b/src/outputlist.cpp index daf3270..c47c1c9 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -196,163 +196,4 @@ void OutputList::parseText(const QCString &textStr) delete root; } - -//-------------------------------------------------------------------------- -// Create some overloaded definitions of the forall function. -// Using template functions here would have made it a little less -// portable (I guess). - -// zero arguments -void OutputList::forall(void (OutputGenerator::*func)()) -{ - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (it.toFirst();(og=it.current());++it) - { - if (og->isEnabled()) (og->*func)(); - } -} - -// one argument -#define FORALL1(a1,p1) \ -void OutputList::forall(void (OutputGenerator::*func)(a1),a1) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1); \ - } \ -} - -// two arguments -#define FORALL2(a1,a2,p1,p2) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2),a1,a2) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2); \ - } \ -} - -// three arguments -#define FORALL3(a1,a2,a3,p1,p2,p3) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3),a1,a2,a3) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3); \ - } \ -} - -// four arguments -#define FORALL4(a1,a2,a3,a4,p1,p2,p3,p4) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4),a1,a2,a3,a4) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3,p4); \ - } \ -} - -// five arguments -#define FORALL5(a1,a2,a3,a4,a5,p1,p2,p3,p4,p5) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5),a1,a2,a3,a4,a5) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3,p4,p5); \ - } \ -} - -// six arguments -#define FORALL6(a1,a2,a3,a4,a5,a6,p1,p2,p3,p4,p5,p6) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5,a6),a1,a2,a3,a4,a5,a6) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3,p4,p5,p6); \ - } \ -} - -// seven arguments -#define FORALL7(a1,a2,a3,a4,a5,a6,a7,p1,p2,p3,p4,p5,p6,p7) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5,a6,a7),a1,a2,a3,a4,a5,a6,a7) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3,p4,p5,p6,p7); \ - } \ -} - - -// eight arguments -#define FORALL8(a1,a2,a3,a4,a5,a6,a7,a8,p1,p2,p3,p4,p5,p6,p7,p8) \ -void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5,a6,a7,a8),a1,a2,a3,a4,a5,a6,a7,a8) \ -{ \ - QListIterator<OutputGenerator> it(m_outputs); \ - OutputGenerator *og; \ - for (it.toFirst();(og=it.current());++it) \ - { \ - if (og->isEnabled()) (og->*func)(p1,p2,p3,p4,p5,p6,p7,p8); \ - } \ -} - -// now instantiate only the ones we need. - -FORALL1(const char *a1,a1) -FORALL1(char a1,a1) -FORALL1(int a1,a1) -FORALL1(DotClassGraph &a1,a1) -FORALL1(DotInclDepGraph &a1,a1) -FORALL1(DotCallGraph &a1,a1) -FORALL1(DotDirDeps &a1,a1) -FORALL1(DotGfxHierarchyTable &a1,a1) -FORALL1(DotGroupCollaboration &a1,a1) -FORALL1(SectionTypes a1,a1) -#if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE) -FORALL1(bool a1,a1) -FORALL2(bool a1,int a2,a1,a2) -FORALL2(bool a1,bool a2,a1,a2) -FORALL2(const char *a1,bool a2,a1,a2) -FORALL4(const char *a1,const char *a2,const char *a3,bool a4,a1,a2,a3,a4) -#endif -FORALL2(int a1,bool a2,a1,a2) -FORALL2(bool a1,const char *a2,a1,a2) -FORALL2(ParamListTypes a1,const char *a2,a1,a2) -FORALL1(IndexSections a1,a1) -FORALL2(const char *a1,const char *a2,a1,a2) -FORALL2(const char *a1,int a2,a1,a2) -FORALL2(const char *a1,SectionInfo::SectionType a2,a1,a2) -FORALL3(bool a1,HighlightedItem a2,const char *a3,a1,a2,a3) -FORALL3(bool a1,bool a2,bool a3,a1,a2,a3) -FORALL3(const ClassDiagram &a1,const char *a2,const char *a3,a1,a2,a3) -FORALL3(const char *a1,const char *a2,const char *a3,a1,a2,a3) -FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3) -FORALL3(const char *a1,int a2,const char *a3,a1,a2,a3) -FORALL3(const char *a1,const char *a2,SectionInfo::SectionType a3,a1,a2,a3) -FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3) -FORALL3(const Definition *a1,const char *a2,bool a3,a1,a2,a3) -FORALL4(SectionTypes a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4) -FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4) -FORALL4(const char *a1,const char *a2,const char *a3,int a4,a1,a2,a3,a4) -FORALL5(const char *a1,const char *a2,const char *a3,const char *a4,const char *a5,a1,a2,a3,a4,a5) -FORALL5(const char *a1,const char *a2,const char *a3,const char *a4,bool a5,a1,a2,a3,a4,a5) -FORALL6(const char *a1,const char *a2,const char *a3,const char *a4,const char *a5,const char *a6,a1,a2,a3,a4,a5,a6) -FORALL6(const char *a1,const DocLinkInfo &a2,const char *a3,const char *a4,const SourceLinkInfo &a5,const SourceLinkInfo &a6,a1,a2,a3,a4,a5,a6) -FORALL7(const char *a1,const char *a2,const char *a3,const char *a4,int a5,int a6,bool a7,a1,a2,a3,a4,a5,a6,a7) - - //-------------------------------------------------------------------------- diff --git a/src/outputlist.h b/src/outputlist.h index 2a83020..cfd3773 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -18,6 +18,7 @@ #ifndef OUTPUTLIST_H #define OUTPUTLIST_H +#include <utility> #include <qlist.h> #include "index.h" // for IndexSections #include "outputgen.h" @@ -109,8 +110,6 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startTitle); } void endTitle() { forall(&OutputGenerator::endTitle); } - //void newParagraph() - //{ forall(&OutputGenerator::newParagraph); } void startParagraph(const char *classDef=0) { forall(&OutputGenerator::startParagraph,classDef); } void endParagraph() @@ -176,8 +175,6 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startGroupHeader,extraLevels); } void endGroupHeader(int extraLevels=0) { forall(&OutputGenerator::endGroupHeader,extraLevels); } - //void writeListItem() - //{ forall(&OutputGenerator::writeListItem); } void startItemListItem() { forall(&OutputGenerator::startItemListItem); } void endItemListItem() @@ -492,70 +489,28 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::addWord,word,hiPriority); } void startPlainFile(const char *name) - { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (;(og=it.current());++it) - { - if (og->isEnabled()) (og->startPlainFile)(name); - } - } + { forall(&OutputGenerator::startPlainFile,name); } void endPlainFile() - { - QListIterator<OutputGenerator> it(m_outputs); - OutputGenerator *og; - for (;(og=it.current());++it) - { - if (og->isEnabled()) (og->endPlainFile)(); - } - } + { forall(&OutputGenerator::endPlainFile); } private: void debug(); void clear(); - void forall(void (OutputGenerator::*func)()); - FORALLPROTO1(const char *); - FORALLPROTO1(char); - FORALLPROTO1(IndexSections); - FORALLPROTO1(int); - FORALLPROTO1(DotClassGraph &); - FORALLPROTO1(DotInclDepGraph &); - FORALLPROTO1(DotCallGraph &); - FORALLPROTO1(DotGroupCollaboration &); - FORALLPROTO1(DotDirDeps &); - FORALLPROTO1(DotGfxHierarchyTable &); - FORALLPROTO1(SectionTypes); -#if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE) - FORALLPROTO1(bool); - FORALLPROTO2(bool,int); - FORALLPROTO2(bool,bool); - FORALLPROTO2(const char *,bool); - FORALLPROTO4(const char *,const char *,const char *,int); -#endif - FORALLPROTO2(int,bool); - FORALLPROTO2(bool,const char *); - FORALLPROTO2(ParamListTypes,const char *); - FORALLPROTO2(const char *,const char *); - FORALLPROTO2(const char *,int); - FORALLPROTO2(const char *,SectionInfo::SectionType); - FORALLPROTO3(bool,HighlightedItem,const char *); - FORALLPROTO3(bool,bool,bool); - FORALLPROTO3(const char *,const char *,bool); - FORALLPROTO3(const char *,int,const char *); - FORALLPROTO3(const char *,const char *,SectionInfo::SectionType); - FORALLPROTO3(uchar,uchar,uchar); - FORALLPROTO3(const char *,const char *,const char *); - FORALLPROTO3(const ClassDiagram &,const char *,const char *); - FORALLPROTO3(const Definition*,const char *,bool); - FORALLPROTO4(SectionTypes,const char *,const char *,const char *); - FORALLPROTO4(const char *,const char *,const char *,const char *); - FORALLPROTO4(const char *,const char *,const char *,bool); - FORALLPROTO5(const char *,const char *,const char *,const char *,const char *); - FORALLPROTO5(const char *,const char *,const char *,const char *,bool); - FORALLPROTO6(const char *,const char *,const char *,const char *,const char *,const char *); - FORALLPROTO6(const char *,const DocLinkInfo &,const char *,const char *,const SourceLinkInfo &,const SourceLinkInfo &); - FORALLPROTO7(const char *,const char *,const char *,const char *,int,int,bool); + // For each output format that is enabled (OutputGenerator::isEnabled()) we forward + // the method call. + // We use C++11 variadic templates and perfect forwarding to implement forall() generically, + // and split the types of the methods from the arguments passed to allow implicit conversions. + template<typename T,class... Ts,class... As> + void forall(void (T::*methodPtr)(Ts...),As&&... args) + { + QListIterator<OutputGenerator> li(m_outputs); + OutputGenerator *og; + for (li.toFirst();(og=li.current());++li) + { + if (og->isEnabled()) (og->*methodPtr)(std::forward<As>(args)...); + } + } OutputList(const OutputList &ol); QList<OutputGenerator> m_outputs; |