How to auto-include all headers in directory

2019-04-06 07:11发布

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 right, and requires too many changes.

Right now I have a single main.cpp file with the following:

#include "e0614.h"
int main()
{
    E0614 ex;
    ex.solve();
}

Each time I create a new class from an exercise, I have to come and modify this file to change the name of the included header as well as the class i'm instantiating.

So my questions are:

  1. Can I include all headers in the directory so at least I don't have to change the #include line?
  2. Better yet, can I rewrite my solution so that I don't even have to touch main.cpp, without having one file with all the code for every exercise in it?

Update:

I ended up following Poita_'s advice to generate main.cpp via a script.

Since I'm using an IDE (Visual Studio), I wanted this integrated with it, so did a bit of research on how. For those interested in how, read on (it was fairly, but not entirely, straightforward).

Visual Studio lets you use an external tool via the Tools -> External Tools menu, and contains a bunch of pre-defined variables, such as $(ItemFileName), which can be passed on to the tool. So in this instance I used a simple batch file, and it gets passed the name of the currently selected file in Visual Studio.

To add that tool to the toolbar, right click on the toolbar, select Customize -> Commands -> Tools, and select the "External Command X" and drag it to the toolbar. Substitute X with the number corresponding to the tool you created. My installation contained 5 default pre-existing tools listed in Tools -> External Tools, so the one I created was tool number 6. You have to figure out this number as it is not shown. You can then assign an icon to the shortcut (it's the BuildMain command shown below):

alt text http://img691.imageshack.us/img691/4853/capturerg.png

标签: c++ include
10条回答
Viruses.
2楼-- · 2019-04-06 07:47
sed -i 's/\<\\([eE]\\)[0-9]+\\>/\19999/' main.cpp

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

查看更多
Juvenile、少年°
3楼-- · 2019-04-06 07:48

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.

查看更多
Explosion°爆炸
4楼-- · 2019-04-06 07:49

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()
查看更多
Rolldiameter
5楼-- · 2019-04-06 07:53

Make a master include file containing the names of all the headers you want.

It's a really bad idea to include *, even if you could.

查看更多
一夜七次
6楼-- · 2019-04-06 07:53

try this:-

#ifndef a_h
#define a_h

#include <iostream>
#include <conio.h>
#incl....as many u like
class a{
f1();//leave it blank
int d;
}
#endif //save this as a.h

later include this in ur main program that is cpp file

#include "a.h"

...your program

查看更多
Anthone
7楼-- · 2019-04-06 07:58

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

查看更多
登录 后发表回答