2

I am in need of some advice on how to setup my project. I'm building a static library and want to know if the way I'm using precompiled headers is correct before I go too far.

So far, my stdafx file is just including (for types like DWORD, etc.) and (for std::string).

I built a simple cpp/header combo called TestFuncs.cpp/h

TestFuncs.cpp:

#include "stdafx.h"
using namespace std;
void MyFunc(DWORD a, string b) {
    // irrelevant
}

TestFuncs.h

#pragma once
void MyFunc(DWORD a, std::string b);

This code here compiles properly. The issue that I have is when I want to use this static library in another project, I would normally do #include "path_to_my_static_lib_project/TestFuncs.h"

However, the issue with this, is based upon TestFuncs.h, both DWORD and string would be unknown at the time, as they are types defined from the stdafx.h file.

One solution that I came up with (that I don't know it's correct to be doing so) is just including stdafx.h at the top of TestFuncs.h after the #pragma once. Now the project works file using precompiled headers or not.

Is this how it should be done, or is there a proper way of doing this?

Thank you.

Matthew
  • 24,703
  • 9
  • 76
  • 110

1 Answers1

6

Don't #include "stdafx.h" in your library's public header file. By public header file, I mean the header file that clients of your library would #include.

Instead, only define the absolute minimum, and preferably use 100% portable code in this file. Also avoid using the STL if your library is going to be used by different compilers or platforms.

So suppose you have a public header file my_library.h which is implemented in gizmo.cpp. You would have the following:

gizmo.cpp

#include "stdafx.h"
#include "my_library.h"

int GizmoTronic()
{ 
  // ...
  return 42;
}

Also, off-topic, but use macro guards and not #pragma once which is not part of the C++ language, and therefore isn't supported by all compilers. It is a bad habit to get in to.

EDIT:

As for the question of DWORD and string not being defined when your header is #include-ed, I have 3 suggestions:

1) Only use portable datatypes. That is, datatypes defined by the Standard. DWORD is a microsoft invention (from decades ago). It is not part of the language, and it is not portable. Instead, use unsigned long or something else suitable.

2) Don't use string in your library's public interface if your library is going to be used by code compiled with a compiler other than yours. The reason is because string is defined completely in header files, so each compiler potentially has it's own implementation. One compiler's string might look different from another's.

3) Assuming #2 doesn't apply, feel free to #include any necesarry headers from the Standard Library at the top of your header. If you use string in your public interface, #include <string> in your header. (Just please do not using namespace std). Your header should be self-contained.

EDIT2:

Here is how I would declare your function:

void MyFunc(unsigned long a, const char* b);
Matthias
  • 4,481
  • 12
  • 45
  • 84
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • In my example the exposed functions of the static library use the DWORD type for one of its parameters. How would you suggest writing the TestFuncs.h file to account for this while still being able to include it in my other projects? – Matthew Nov 15 '10 at 03:55
  • Use a portable datatype, instead of something invented by microsoft. For example, instead of using `DWORD`, use `unsigned long`. – John Dibling Nov 15 '10 at 04:07
  • 2
    On the contrary, `#pragma once` is more than safe to use in cross-platform code. Most if not all modern compilers, including GCC 3.4+, handle it correctly. The reason it's not part of the official standard, however, is because of the problems inherent in its design. In a nutshell, `#pragma once` is harder for the compiler to optimize and more ambiguous in its meaning than old-fashioned `#include` guards. (See this [very well-written answer](http://stackoverflow.com/a/1696194/266704) for details.) In the end, you have to decide whether the added convenience is worth the longer build times. – andrewtc Sep 05 '14 at 08:23