How to auto-include all headers in directory

前端 未结 10 3201
被撕碎了的回忆
被撕碎了的回忆 2021-02-20 12:32

I\'m going through exercises of a C++ book. For each exercise I want to minimize the boilerplate code I have to write. I\'ve set up my project a certain way but it doesn\'t seem

相关标签:
10条回答
  • 2021-02-20 12:37

    You could use conditional compilation for the class name by using concatenation.

    // Somewhere in your other files
    define CLASS_NUMBER E0614
    
    // in main.cpp
    #define ENTERCLASSNUMBER(num) \
    ##num## ex;
    
    // in main()
    ENTERCLASSNUMBER(CLASS_NUMBER)
    

    Don't know about the includes though. As suggested above, a script might be the best option.

    0 讨论(0)
  • 2021-02-20 12:45
    1. No. You have to include them all if that's what you want to do.

    2. No. At least, not in a way that's actually going to save typing.

    Of course, you could write a script to create main.cpp for you...

    0 讨论(0)
  • 2021-02-20 12:49

    If you're on Unix system, you can have a softlink that points to the latest excercise.

    ln -s e0615.h latest.h

    and name your class E instead of E0614, of course

    P.S. To the best of my knowledge, you can't do #include xxx*

    0 讨论(0)
  • 2021-02-20 12:51

    Why not using object mechanisms ?

    You can use an Exemplar strategy for this.

    class BaseExercise
    {
    public:
      static bool Add(BaseExercise* b) { Collection().push_back(b); return true; }
      static size_t Solve() {
        size_t nbErrors = 0;
        for(collections_type::const_iterator it = Collection().begin(), end = Collection().end(); it != end; ++it)
          nbErrors += it->solve();
        return nbErrors;
      }
    
      size_t solve() const
      {
        try {
          this->solveImpl();
          return 0;
        } catch(std::exception& e) {
          std::cout << mName << " - end - " << e.what() << std::endl;
          return 1;
        }
      }
    protected:
      explicit BaseExercise(const char* name): mName(name)
      {
      }
    private:
      typedef std::vector<BaseExercise*> collection_type;
      static collection_type& Collection() { collection_type MCollection; return MCollection; }
    
      virtual void solveImpl() const = 0;
    
      const char* mName;
    }; // class BaseExercise
    
    template <class T>
    class BaseExerciseT: public BaseExercise
    {
    protected:
      explicit BaseExerciseT(const char* b): BaseExercise(b) { 
        static bool MRegistered = BaseExercise::Add(this);
      }
    };
    

    Okay, that's the base.

    // Exercise007.h
    #include "baseExercise.h"
    
    class Exercise007: public BaseExerciseT<Exercise007>
    {
    public:
      Exercise007(): BaseExerciseT<Exercise007>("Exercise007") {}
    private:
      virtual void solveImpl() const { ... }
    };
    
    // Exercise007.cpp
    Exercise007 gExemplar007;
    

    And for main

    // main.cpp
    #include "baseExercise.h"
    
    int main(int argc, char* argv[])
    {
      size_t nbErrors = BaseExercise::Solve();
      if (nbErrors) std::cout << nbErrors << " errors" << std::endl;
      return nbErrors;
    }
    

    And here, you don't need any script ;)

    0 讨论(0)
  • 2021-02-20 12:53

    Don't use one main.cpp which you modify for each exercise. This solution makes use of make's builtin rules, so you only have to type make e0614 and it will generate e0614.cpp, compile, and link it. You can customize each .cpp file (they won't be regenerated as written below) and maintain all of that history to refer to as you complete exercises, rather than erasing it as you move from one to the next. (You should also use source control, such as Mercurial.)

    Makefile

    e%.cpp:
            ./gen_ex_cpp $@ > $@
    

    You can generate boilerplate code with scripts, because you don't want it to be tedious either. There are several options for these scripts—and I use a variety of languages including C++, Python, and shell—but the Python below is short and should be simple and clear enough here.

    Sample generate script

    #!/usr/bin/python
    import sys
    args = sys.argv[1:]
    if not args:
      sys.exit("expected filename")
    name = args.pop(0).partition(".")[0]
    if args:
      sys.exit("unexpected args")
    upper_name = name.upper()
    print """
    #include "%(name)s.hpp"
    int main() {
      %(upper_name)s ex;
      ex.solve();
      return 0;
    }
    """ % locals()
    
    0 讨论(0)
  • 2021-02-20 12:53
    sed -i 's/\<\\([eE]\\)[0-9]+\\>/\19999/' main.cpp
    

    Replace 9999 with the required number. There might be better ways.

    0 讨论(0)
提交回复
热议问题