3

I added #ifndef..#define..#endif to a file of my project and the compiler fails. As soon as I remove it or put any other name in the define it compiles fine. What could be the problem?

Sounds like the file is already declared, but I do not know where. I'm fine just removing it, but I really want to know why this is happening.

error: expected class-name before ‘{’ token
error: ‘QDesignerFormEditorInterface’ has not been declared

And a couple of other errors.

I am actually using an example from Qt, "Custom Widget Plugin Example".

The difference is I am using my own class for the custom widget (.h, .cpp and .ui file).

It might have to do with the file that has 2 includes, though that is how the example did it.

Wolf
  • 9,679
  • 7
  • 62
  • 108
yan bellavance
  • 4,710
  • 20
  • 62
  • 93
  • 3
    Describe the file. Explain what #ifndef you're adding and why. If it's the standard include guard, and you're doing it right, then you're probably duplicating the include guard name. Search for it in your codebase, and use more distinct names in the future (names based directly on the whole file name are usually safe). – David Thornley Nov 16 '09 at 19:06
  • It's not the build that failed, but just one compilation unit. It's a compile-time error, so adding the unit that failed to compile would definitely have been possible. – Wolf Nov 13 '17 at 11:30

2 Answers2

30

Is this macro used as an include guard? If so, it sounds like you're duplicating a name used elsewhere. This is a common problem when people don't think about the scope an include guard must have—you should include much more information in it than just the file name.

Include guard goals:

  • generate once, when creating a header
  • never have to think about again
  • chance of duplicating is less than your chance of winning the lottery

Bad include guard names (for file "config.h"):

  • CONFIG_H
    • much too general
  • _CONFIG_H, CONFIG__H, CONFIG_H__, __CONFIG_H__, etc.
  • PROJECT_CONFIG_H
    • better, much less likely to duplicate in unrelated projects
    • but still no path information, easy to duplicate in large projects

Good include guard names (for file "config.h"):

  • PATE_20091116_142045
    • that's <last name>_<date>_<time>
    • no project, path, filename information even needed
    • easy to type
      • if your editor has an insert-date feature, you can "type" it very fast
    • easy to generate
      • include a sequence number when generating, if you need to generate more than one per second
    • strong guarantee of being universally unique
  • INCLUDE_GUARD_726F6B522BAA40A0B7F73C380AD37E6B
    • generated from an actual UUID
      • strong guarantee of being universally unique
    • if it turns up unexpectedly, "INCLUDE_GUARD" is a good hint about what it is, while serving to put it in a separate namespace (though by convention rather than recognized by the language)
    • prepend a project name, if desired (which is often required by project guidelines for macros)
    • easy to write your own sample program to generate
  • 8
    #pragma once - the best include guard (if supported by your target compilers) – sbk Nov 16 '09 at 20:34
  • 8
    Except the #pragma introduces the debate about support and being non-standard, with no additional benefit. It's easy to use include guards. –  Nov 25 '09 at 20:53
  • 1
    A potential additional benefit is that the compiler could build a collection of header file names that have had #pragma once used in them and never even open the file again rather than having to open the file, read it all, parse it and ignore it. That said I use both and have the #pragma once protected by a compiler version check ... – Len Holgate Nov 25 '09 at 20:57
  • 10
    The compiler can do that with include guards. GCC has done this for years, and I heard MSVC does now too. A significant problem is how to handle things like links (both symbolic and hard)--the #pragma fails, but include guards work. –  Nov 25 '09 at 21:06
3

If you add an #ifndef for a constant that's already defined, it will always validate to true. You say "the file is declared", but files do not get declared. It is really the constant that you place after #ifndef that you should be checking. Do a simple search through the whole source tree and double-check in what order your current #define appears.

And of course: is your code correct? Try with a rubbish name as constant, and place #endif right after it: if it still errors, you have typos (paste your code, if so). See also this post.

PS: I see that David Thornley was typing similar advice in a comment... sorry if this duplicates info in this thread.

Abel
  • 56,041
  • 24
  • 146
  • 247
  • as I said, everything compiles fine when I put rubbish as the constant. – yan bellavance Nov 16 '09 at 19:34
  • then, sounds to me you should use rubbish indeed (the name really doesn't matter) as the name causing trouble is apparently declared elsewhere already. As mentioned in the other answer, the constant can be any name. If the scope is only local, then don't bother and keep your working rubbish-like name. – Abel Nov 16 '09 at 20:07
  • I was hoping to understand why this is so. – yan bellavance Nov 16 '09 at 21:16
  • 1
    Maybe I wasn't clear. Make sure to take a good look at Pate's answer, it's rather extensive. If `XYZ` is defined, and you have `#ifndef XYZ`, it will always fail. If you want the reverse, use a name that's not defined. That's all the *"why"* there is to it, I'm afraid. – Abel Nov 16 '09 at 23:55
  • ok I will look into it..sorry i am at work and didnt have much time today to look at it. Thx for your answers though – yan bellavance Nov 17 '09 at 01:54